diff --git a/.drone.yml b/.drone.yml index 801636b..a729deb 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,8 +6,8 @@ steps: - name: build image: node:current environment: - REPOSITORY: - GIT_USER: + REPOSITORY: spoonfairies-site + GIT_USER: inherentlee GIT_TOKEN: from_secret: GIT_TOKEN commands: diff --git a/LICENSE b/LICENSE index 7942b72..db8a4b3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ - +Spoonfairies Copyright (C) 2026 Lee Cattarin This program is free software: you can redistribute it and/or modify diff --git a/_config/filters.js b/_config/filters.js index 5de64dc..4587047 100644 --- a/_config/filters.js +++ b/_config/filters.js @@ -1,6 +1,18 @@ import { DateTime } from "luxon"; export default function (eleventyConfig) { + /* Filter out a given url from the collection */ + eleventyConfig.addFilter("excludeFromCollection", function (collection=[], pageUrl=this.ctx.page.url) { + return collection.filter(post => post.url !== pageUrl); + }); + + /* Return only the collection items that match one or more tags */ + eleventyConfig.addFilter("filterByTags", function(collection=[], ...requiredTags) { + return collection.filter(post => { + return requiredTags.flat().some(tag => post.data.tags.includes(tag)); + }); + }); + /* Return the keys used in an object */ eleventyConfig.addFilter("getKeys", (target) => { return Object.keys(target); @@ -49,7 +61,7 @@ export default function (eleventyConfig) { /* Filter out structural tags */ eleventyConfig.addFilter("removeBasicTags", (tags) => { - return tags.filter((tag) => ["all"].indexOf(tag) === -1); + return tags.filter((tag) => ["all", "doublePagination"].indexOf(tag) === -1); }); /* What it says on the tin */ diff --git a/_data/metadata.js b/_data/metadata.js index 8ccc1e9..9bdd33d 100644 --- a/_data/metadata.js +++ b/_data/metadata.js @@ -1,6 +1,6 @@ export default { - title: "", - description: "", - url: "", + title: "Spoonfairies", + description: "find the services you need from others who need you", + url: "https://spoonfairies.help", author: "Lee Cattarin", }; diff --git a/_includes/footer.njk b/_includes/footer.njk index 5e0ea02..2526c34 100644 --- a/_includes/footer.njk +++ b/_includes/footer.njk @@ -1,2 +1,10 @@ diff --git a/_includes/head.njk b/_includes/head.njk index 782650a..7bad872 100644 --- a/_includes/head.njk +++ b/_includes/head.njk @@ -18,24 +18,23 @@ - {# - - - #} - - {# - - #} + + + + + + + + - {# + - #} diff --git a/_includes/header.njk b/_includes/header.njk index 7837725..979d22b 100644 --- a/_includes/header.njk +++ b/_includes/header.njk @@ -1,4 +1,14 @@
-
diff --git a/_includes/layouts/page.njk b/_includes/layouts/page.njk deleted file mode 100644 index 44515f9..0000000 --- a/_includes/layouts/page.njk +++ /dev/null @@ -1,7 +0,0 @@ ---- -layout: base.njk ---- - -

{{ title }}

- -{{ content | safe }} diff --git a/_includes/layouts/provider.njk b/_includes/layouts/provider.njk new file mode 100644 index 0000000..cfe788a --- /dev/null +++ b/_includes/layouts/provider.njk @@ -0,0 +1,42 @@ +--- +layout: base.njk +--- + +
+

{{ title }} + {% if pronouns %}{{ pronouns }}{% endif %} +

+ + + + {{ content | safe }} + + {% if contacts %} +

contact information

+
    + {% for contact in contacts %} +
  • + {% if contact.href %} + {{ contact.title }} + {% else %} + {{ contact.title }} + {% endif %} +
  • + {% endfor %} +
+ {% endif %} +
+ + diff --git a/_includes/providerlist.njk b/_includes/providerlist.njk new file mode 100644 index 0000000..e667097 --- /dev/null +++ b/_includes/providerlist.njk @@ -0,0 +1,20 @@ + diff --git a/_includes/taglist.njk b/_includes/taglist.njk new file mode 100644 index 0000000..f9d3470 --- /dev/null +++ b/_includes/taglist.njk @@ -0,0 +1,7 @@ +

services this provider offers are

+
    + {%- for tag in tags | removeBasicTags %} + {%- set tagUrl %}/services/{{ tag | slugify }}/{% endset %} +
  • {%- if not loop.last %}, {% endif %}
  • + {%- endfor %} +
diff --git a/css/main.css b/css/main.css index 0b75e82..9e5463e 100644 --- a/css/main.css +++ b/css/main.css @@ -1,5 +1,26 @@ :root { color-scheme: light dark; + + --font-family: "Atkinson Hyperlegible Next", sans-serif; + + /* Theme colors */ + --color-light: #fbe8fd; + --color-dark: #110526; + + --color-pink-dark: #741189; + --color-pink-light: #d972ef; + --color-purple-dark: #421397; + --color-purple-light: #9d6ff4; + --color-blue-dark: #1243a7; + --color-blue-light: #6586ea; + + /* light/dark mode resolved colors */ + --color-bg: light-dark(var(--color-light), var(--color-dark)); + --color-text: light-dark(var(--color-dark), var(--color-light)); + + --color-pink: light-dark(var(--color-pink-dark), var(--color-pink-light)); + --color-purple: light-dark(var(--color-purple-dark), var(--color-purple-light)); + --color-blue: light-dark(var(--color-blue-dark), var(--color-blue-light)); } /* numbered components are from https://www.joshwcomeau.com/css/custom-css-reset/ */ @@ -7,8 +28,8 @@ box-sizing: border-box; /* 1. Use a more-intuitive box-sizing model */ } -*:not(dialog) { - margin: 0; /* 2. Remove default margin */ +#root, #__next { + isolation: isolate; /* 10. Create a root stacking context */ } @media (prefers-reduced-motion: no-preference) { @@ -17,11 +38,33 @@ } } +html, body { + padding: 0; + margin: 0 auto; + font-family: var(--font-family); + color: var(--color-text); + background-color: var(--color-bg); +} + +html { + overflow-y: scroll; +} + +body { + max-width: 40rem; line-height: 1.5; /* 4. Increase line-height */ -webkit-font-smoothing: antialiased; /* 5. Improve text rendering */ } +main { + padding: 1rem; +} + +section + section { + margin-top: 4rem;; +} + img, picture, video, canvas, svg { display: block; /* 6. Improve media defaults */ max-width: 100%; /* 6. Improve media defaults */ @@ -40,10 +83,238 @@ p { text-wrap: pretty; /* 9. Improve line wrapping */ } +p:last-child { + margin-bottom: 0; +} +p { + line-height: 1.5; +} +p + p { + margin-top: 2rem; +} + h1, h2, h3, h4, h5, h6 { text-wrap: balance; /* 9. Improve line wrapping */ } -#root, #__next { - isolation: isolate; /* 10. Create a root stacking context */ +h1 { + font-size: 2.5rem; + margin-top: 0; +} +h2 { + font-size: 1.9rem; + padding-bottom: .1rem; + border-bottom: .1rem solid var(--color-pink); +} +h3 { + font-size: 1.5rem; + padding-bottom: .05rem; + border-bottom: .05rem solid var(--color-pink); +} +h4 { + font-size: 1.2rem; +} + +li { + line-height: 1.5; +} +.long-items li + li { + margin-top: .75rem; +} + +a { + color: var(--color-text); + text-decoration-thickness: .2rem; + text-decoration-color: var(--color-blue); + border-radius: .1rem; + outline-offset: .1rem; +} +a:visited { + text-decoration-color: var(--color-purple); +} +a:hover, +a:active { + text-decoration-color: var(--color-pink); +} +a:focus-visible { + text-decoration: none; + outline: .15rem solid var(--color-pink); +} +a.ha { + color: var(--color-pink); + outline-offset: 0; +} +span.ha-placeholder { + opacity: .55; +} + +/* https://www.a11yproject.com/posts/how-to-hide-content/ */ +.visually-hidden:not(:focus):not(:active) { + clip: rect(0 0 0 0); + clip-path: inset(50%); + height: 1px; + overflow: hidden; + position: absolute; + white-space: nowrap; + width: 1px; +} + +/* name coloration */ +.brand { + color: var(--color-pink); + font-weight: bold; +} + +/* provider pronouns */ +.pronouns::after { + content: ")" / ""; +} +.pronouns::before { + content: "(pronouns: " / "pronouns: "; +} +.pronouns { + color: var(--color-text); + opacity: .75; + font-size: .8em; +} + +/* location spans */ +.location::before { + content: "📍" / "is based out of "; +} +.online::before { + content: "🌐" / "is "; +} +.location, +.online { + margin: 0; + text-align: right; + color: var(--color-text); + font-size: 1rem; + font-weight: bold; +} + +/* Posts list */ +.providerlist { + padding: 0; +} +.providerlist-item { + display: flex; + flex-wrap: wrap; + align-items: baseline; + margin-bottom: 1rem; +} +.providerlist-item + .providerlist-item { + border-top: .1rem dotted; + margin-top: 2.25rem; + padding-top: 1.5rem; +} +.providerlist-link { + font-size: 1.35rem; /* 19px /16 */ + font-weight: 700; + flex-basis: 100%; + border-bottom: .05rem solid var(--color-pink); + text-decoration: none; + color: var(--color-blue); + display: inline-flex; + align-items: baseline; + column-gap: .5rem; + flex-flow: row wrap; +} +.providerlist-link:visited { + color: var(--color-purple); +} +.providerlist-link:hover, +.providerlist-link:active { + color: var(--color-pink); +} +.providerlist-link:focus-visible { + border-bottom-color: var(--color-bg); +} +.providerlist-link .location, +.providerlist-link .online { + flex-grow: 5; +} +.providerlist-item-active .providerlist-link { + font-weight: bold; +} + +/* Tags */ +.post-tag { + display: inline-block; + font-style: italic; +} + +/* Tags list */ +.taglist { + display: inline-flex; + flex-wrap: wrap; + column-gap: .5rem; + list-style: none; + padding: 0; + margin: 0; +} + +/* related providers section on provider pages */ +.related-providers { + border-top: .1rem dotted; + padding-top: 1rem; + margin-top: 4rem; +} + +/* services page */ +.service-list { + display: flex; + flex-flow: row wrap; + padding-left: 0; + column-gap: 1rem; + row-gap: 2rem; + margin-top: 3rem; +} +.service { + list-style: none; +} +.service a { + border: .1rem dotted; + padding: .5rem; + border-radius: .75rem; +} +.service a:focus-visible { + border-color: var(--color-bg); +} + +/* post metadata */ +.post-metadata { + display: flex; + flex-flow: column nowrap; + align-items: flex-end; + gap: .5rem; +} +.post-time { + font-size: .9rem; + opacity: .75; + margin: 0; +} +@media (max-width: 500px) { + .post-metadata .taglist { + justify-content: flex-end; + } +} + +/* provider contact info */ +.contacts { + text-align: center; + padding: 0; +} +.contacts li { + list-style: none; +} +.contacts li + li { + padding-top: .75rem; +} + +/* team page specific */ +.team-contact { + display: block; + text-align: center; } diff --git a/css/nav.css b/css/nav.css new file mode 100644 index 0000000..34d2b78 --- /dev/null +++ b/css/nav.css @@ -0,0 +1,132 @@ +header { + border-bottom: .2rem dotted; + display: flex; + gap: 1rem; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + padding: 1rem; +} + +#skip-link { + text-decoration: none; + background: var(--color-bg); + color: var(--color-text); + padding: 0.5rem 1rem; + outline-offset: 0; + border-radius: .25rem; +} +/* Prevent visually-hidden skip link fom pushing content around when focused */ +#skip-link.visually-hidden:focus { + position: absolute; + top: 1rem; + left: 1rem; + /* Ensure it is positioned on top of everything else when it is shown */ + z-index: 999; +} + +/* logo and title */ +.home-link { + font-weight: 700; + border-radius: .25rem; + display: flex; + gap: .5rem; + outline-offset: .25rem; + text-underline-offset: .2rem; +} +.home-link:link:not(:hover) { + text-decoration: none; +} +a[href].home-link:focus-visible { + outline-width: .25rem; +} + +header img { + height: 3rem !important; + width: 3rem !important; + border-radius: .5rem; +} + +header h2 { + margin: 0; + outline-offset: .25rem; + border: none; + text-transform: lowercase; + color: var(--color-pink); +} +header a:has(h2):hover { + text-decoration-color: var(--color-text); +} + +/* Nav */ +.nav { + display: flex; + gap: .5rem 1rem; + padding: 0; + margin: 0; + list-style: none; +} +.nav-item { + display: inline-block; +} +.nav a[href][aria-current="page"] { + text-decoration: underline; + text-decoration-thickness: .2rem; +} +.nav a[href][aria-current="page"]:hover { + text-decoration-color: var(--color-pink); +} + +/* Pagination */ +.pagination { + display: flex; + justify-content: space-between; + gap: 1rem; + border-top: .2rem dotted; + margin-top: 2.25rem; + padding-top: 2rem; + padding-left: 0; +} +.pagination li { + list-style: none; +} +.pagination li:not(:has(a)), +.pagination a { + display: block; + border: .1rem dotted; + padding: .5rem; + border-radius: .75rem; +} + +/* Footer */ +footer { + border-top: .2rem dotted; + margin-top: 1.5rem; + padding: 1rem 0; + text-align: center; +} +.footer-links { + display: flex; + gap: 1rem; + justify-content: space-between; +} +footer p { + margin: 0; +} +footer .year { + width: 30%; + padding-top: .5rem; + margin: 1rem auto; + border-top: .05rem solid; +} + +@media (max-width: 500px) { + .footer-links { + flex-flow: column; + gap: .1rem; + align-items: center; + } + footer .year { + width: 65%; + } +} diff --git a/eleventy.config.js b/eleventy.config.js index da72b19..2b5ad5e 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -1,11 +1,13 @@ import { HtmlBasePlugin } from "@11ty/eleventy"; import { eleventyImageTransformPlugin } from "@11ty/eleventy-img"; +import pluginNavigation from "@11ty/eleventy-navigation"; import { attrs } from "@mdit/plugin-attrs"; import { markdownitLinkAttributes } from 'markdown-it-link-attributes'; import markdownitIdAttributes from "markdown-it-anchor"; import path from "node:path"; +import { chunk } from "lodash-es"; import pluginFilters from "./_config/filters.js"; @@ -43,6 +45,32 @@ export default async function (eleventyConfig) { bundleHtmlContentFromSelector: "script", }); + /* Paginate tags */ + eleventyConfig.addCollection("doublePagination", function(collection) { + // Get unique list of tags + let tagSet = new Set(collection.getAllSorted().flatMap((post) => post.data.tags || [])); + + // Get each item that matches the tag + let paginationSize = 20; + let tagMap = []; + let tagArray = [...tagSet]; + for( let tagName of tagArray) { + let tagItems = collection.getFilteredByTag(tagName); + let pagedItems = chunk(tagItems.reverse(), paginationSize); // console.log( tagName, tagItems.length, pagedItems.length ); + for( let pageNumber = 0, max = pagedItems.length; pageNumber < max; pageNumber++) { + tagMap.push({ + tagName: tagName, + pageNumber: pageNumber, + pageSize: pagedItems.length, + pageData: pagedItems[pageNumber] + }); + } + } + + //console.log( tagMap ); + return tagMap; + }); + /* Passthroughs */ eleventyConfig .addPassthroughCopy("favicon.ico") @@ -76,6 +104,9 @@ export default async function (eleventyConfig) { }, }); + /* Navigation */ + eleventyConfig.addPlugin(pluginNavigation); + /* All filters from _config/filters.js */ eleventyConfig.addPlugin(pluginFilters); diff --git a/favicon.ico b/favicon.ico new file mode 100755 index 0000000..770a702 Binary files /dev/null and b/favicon.ico differ diff --git a/package-lock.json b/package-lock.json index 01509e5..c64aa48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,10 @@ "devDependencies": { "@11ty/eleventy": "^3.1.5", "@11ty/eleventy-img": "^6.0.4", + "@11ty/eleventy-navigation": "^1.0.5", "@mdit/plugin-attrs": "^0.25.1", + "@zachleat/heading-anchors": "^1.0.5", + "lodash-es": "^4.18.1", "luxon": "^3.7.2", "markdown-it-anchor": "^10.0.0", "markdown-it-link-attributes": "https://github.com/lee0c/markdown-it-link-attributes/tarball/main" @@ -168,6 +171,20 @@ "url": "https://opencollective.com/11ty" } }, + "node_modules/@11ty/eleventy-navigation": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-navigation/-/eleventy-navigation-1.0.5.tgz", + "integrity": "sha512-zb6xe29cM9viSdYtZywKIkJw2HIROyBINdBcFWC9uD0c/jYOTAex5nwy3HNEuh5t6/Ld/S9V4gEizfmeYuYpCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dependency-graph": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, "node_modules/@11ty/eleventy-plugin-bundle": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@11ty/eleventy-plugin-bundle/-/eleventy-plugin-bundle-3.0.7.tgz", @@ -785,6 +802,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@zachleat/heading-anchors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@zachleat/heading-anchors/-/heading-anchors-1.0.5.tgz", + "integrity": "sha512-hsAljmm6py9VEf6ToKGyQJweemQJM4bI75TTTbwRYIrasCm66ajJDhWYpgZJM1B+8KSop371RDhDASYl3Q4y9g==", + "dev": true, + "license": "MIT" + }, "node_modules/a-sync-waterfall": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", @@ -1762,6 +1786,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "dev": true, + "license": "MIT" + }, "node_modules/luxon": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", diff --git a/package.json b/package.json index 59f1f32..109840a 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,10 @@ "devDependencies": { "@11ty/eleventy": "^3.1.5", "@11ty/eleventy-img": "^6.0.4", + "@11ty/eleventy-navigation": "^1.0.5", "@mdit/plugin-attrs": "^0.25.1", + "@zachleat/heading-anchors": "^1.0.5", + "lodash-es": "^4.18.1", "luxon": "^3.7.2", "markdown-it-anchor": "^10.0.0", "markdown-it-link-attributes": "https://github.com/lee0c/markdown-it-link-attributes/tarball/main" diff --git a/src/accessibility.md b/src/accessibility.md new file mode 100644 index 0000000..c0fcf75 --- /dev/null +++ b/src/accessibility.md @@ -0,0 +1,58 @@ +--- +title: accessibility +--- + +# Spoonfairies accessibility + +
+ +## program accessibility statement + +tbd + +
+ +
+ +## site accessibility statement + +This is an accessibility statement from Spoonfairies. + +### measures to support accessibility + +Spoonfairies takes the following measures to ensure accessibility: + +- Include accessibility throughout our internal policies. +- Integrate accessibility into our procurement practices. +- Assign clear accessibility goals and responsibilities. +- Center disabled people in our program. + +### conformance status + +The [Web Content Accessibility Guidelines (WCAG)](https://www.w3.org/WAI/standards-guidelines/wcag/) defines requirements for designers and developers to improve accessibility for people with disabilities. It defines three levels of conformance: Level A, Level AA, and Level AAA. Spoonfairies is, to the best of our knowledge, fully conformant with WCAG 2.2 level AA. Fully conformant means that the content fully conforms to the accessibility standard without any exceptions. + +### feedback + +We welcome your feedback on the accessibility of Spoonfairies. Please let us know if you encounter accessibility barriers via [any of the contact methods listed for Lee Cattarin](https://leecat.art). + +### technical specifications + +Accessibility of Spoonfairies relies on the following technologies to work with the particular combination of web browser and any assistive technologies or plugins installed on your computer: + +- HTML +- CSS +- JavaScript + +These technologies are relied upon for conformance with the accessibility standards used. + +### assessment approach + +We assessed the accessibility of Spoonfairies by the following approaches: + +- Self-evaluation + +### date + +This statement was created on 4 February 2026 using the [W3C Accessibility Statement Generator Tool](https://www.w3.org/WAI/planning/statements/). + +
diff --git a/src/attribution.md b/src/attribution.md new file mode 100644 index 0000000..d586e96 --- /dev/null +++ b/src/attribution.md @@ -0,0 +1,13 @@ +--- +title: attribution +--- + +# attribution + +This site is built using [{{ eleventy.generator }}](https://www.11ty.dev/) by [Lee Cattarin](https://leecat.art). It is hosted by [heckin' technology](https://heckin.technology/), "a small, weird, mostly indigenous, autistic game and software and art cooperative." + +The font is [Atkinson Hyperlegible Next](https://brailleinstitute.org/freefont), specifically designed for low-vision readers to improve character recognition. + +v1 of this site was built from the [Eleventy base blog template](https://github.com/11ty/eleventy-base-blog). + +This site is created [without the use of generative AI](https://declare-ai.org/1.0.0/none.html). diff --git a/src/get-involved.md b/src/get-involved.md new file mode 100644 index 0000000..a77b9e9 --- /dev/null +++ b/src/get-involved.md @@ -0,0 +1,86 @@ +--- +eleventyNavigation: + key: get involved + order: 3 +title: get involved +--- + +# get involved with Spoonfairies + +
+ +## location + +Spoonfairies is currently focused on Seattle and the Puget Sound, though we can accept digital-only providers from all over. If you're outside of this region and would like to offer physical services, please [talk to someone on the core team](/team#core) about extending Spoonfairies' reach. + +
+ +
+ +## our values + +We ask that all providers and clients uphold our core values as part of their participation. + +
    +
  • + Community: we aim to create, nurture, and sustain a + community of providers actively seeking to promote collective wellness, + healing, and support for marginalized people. +
  • +
  • + Adaptability: we embrace change and challenges with + enthusiasm and creativity. Our core purpose is to cater our model to meet + the needs of those in our community, ever growing and furthering the goals + of social equitability, justice, and wellness. This means our model and all + outreach should be accessible across all identities & needs. +
  • +
  • + Love: we approach all interactions wholeheartedly, with + the primary purpose of extending love and kindness into our community. +
  • +
  • + Health: we disrupt the cycle of capitalist exploitation + by honoring the health and wellness of our providers and members; we honor + our own health needs and actively encourage our community to prioritize + their well-being over capitalist interest by facilitating livable wages, + communal support, and collective healing. +
  • +
  • + Dignity: we create systems and processes that allow for + providers to fully experience the diverse complexities of everyday life. + We believe that every person deserves to have livable wages and sustainable + work/life balance, and we celebrate our providers' "no". +
  • +
+ +
+ +
+ +## as a provider + +Sign up using [our sign-up form](https://airtable.com/appTNSejknPJEEdrN/pagzaSgmO9bnFVgTt/form) — or email Lee if Airtable (our form provider) is inaccessible to you. + +
+ +
+ +## as a client + +View the [provider directory](/providers) or [browse by service](/services) to find relevant providers. + +If a given provider does not have a contact method that works for you, reach out to [someone on the team](/team) and we'll get in contact with them for you. + +Overwhelmed by choices? Email Bex if you need help navigating providers and services. + +
+ +
+ +## testimonials + +Clients and providers are strongly encouraged to submit testimonials about their experiences with a given provider or with the Spoonfairies program as a whole. + +You can submit a testimonial using our [testimonial form](https://airtable.com/appTNSejknPJEEdrN/pagBkMSqVTVXDCkAa/form) — or email Lee if Airtable (our form provider) is inaccessible to you. + +
diff --git a/src/index.md b/src/index.md new file mode 100644 index 0000000..7a13226 --- /dev/null +++ b/src/index.md @@ -0,0 +1,111 @@ +
+ +# about Spoonfairies + +Spoonfairies is a project to connect people: those who need help and those who can provide it, with the ability to move fluidly between these groups or occupy both. + +Spoonfairies is currently focused on Seattle and the Puget Sound region, but digital-only participation can come from all over. + +
+ +
+ +## ethos + +### universal worth + +Everyone needs and deserves help, and everyone has skills that can better their community. Everyone deserves access to the support and income they need to live their best life. + +### person-centered pricing + +We are all of equal value and deserve living wages for expending our time and energy. No service is inherently worth any more than another because no person or their time is worth more than another’s. + +### alternatives to capitalism + +We must build our own support system to build and keep wealth within our communities and provide the services and infrastructures we need to survive. + +
+ +
+ +## Spoonfairies can look like... + +### client + +- J has a sister with long COVID who needs help with some household tasks. He wants to gift her 5 hrs of cleaning services, so he sets her up with a Spoonfairies provider he's already arranged payment with +- M is a busy parent who can forget to take care of herself. She signs up for a weekly check-in service to ensure her own goals move forward +- X is a tech worker who hates going to the grocery store. Ze finds a provider to help with weekly grocery delivery and a monthly Costco run + +### provider + +- L is a stay at home parent with ADHD who loves to cook and provides weekly meal prep & delivery for 25 neurodivergent queerdos in her area at good hourly wage +- Q, a car mechanic, owns a queer/neurodivergent friendly business. She offers 10 hrs of services per month to Spoonfairies clients at friends-and-family rates +- D has a part-time job bookkeeping for a larger firm. In their free time, they use their skills to provide monthly accounting services to a handful of clients’ small businesses in exchange for business discounts + +### or both + +- Z, an agoraphobic autistic with OCD who is excellent at organization and graphic design, provides admin design services and receives grocery/med delivery and occasional cleaning help. +- C is on disability and navigating income/wealth cap. Xe runs virtual body doubling services and barters some of xe's work for other services. + +
+ +
+ +## example services + +### executive function + +#### recurring + +- Weekly check-ins – "Life Boss" +- Life coach – neurodivergent strategies & resources + +#### on demand + +- Body doubling/errand hangs +- Custom organizers/graphics for household/personal routines +- Neurodivergent advocate/educator (landlords, bosses, families/partners) + +### physical & mental health + +#### recurring + +- Prescription pick-up/renewal reminders +- Transportation to/from appointments +- Medical advocacy at appointments +- Peer counseling + +#### on demand + +- Provider research +- Appointment scheduling +- Benefits navigation + +### home and personal spaces + +#### recurring + +- Recurring cleaning/chore help +- Recurring grocery delivery/meal plan/prep +- Recurring appliance/vehicle maintenance + +#### on demand + +- Organization/room design +- De-funk your space + +### administrative + +#### recurring + +- Email/calendar management +- Scheduling support +- Budget tracking/personal finance support + +#### on demand + +- Event planning +- Job search support +- Travel booking/vacation planning + +
diff --git a/src/logo.jpg b/src/logo.jpg new file mode 100755 index 0000000..770a702 Binary files /dev/null and b/src/logo.jpg differ diff --git a/src/privacy.md b/src/privacy.md new file mode 100644 index 0000000..3ed930d --- /dev/null +++ b/src/privacy.md @@ -0,0 +1,29 @@ +--- +title: privacy +--- + +# privacy + +
+ +## provider privacy + +Providers sign up via Airtable. [Read more on Airtable's privacy policy with regard to user content](https://www.airtable.com/company/privacy#a-use-of-content). + +Airtable access is limited to the [core Spoonfairies organizing team](/team#core). + +Sign-up makes clear what provided information is available on our public-facing website. No other information is provided to prospective clients or other parties. + +Providers may [reach out to someone on the core team](/team#core) at any time regarding removal from the site and deletion of their information. + +
+ +
+ +## client privacy + +Clients reach out directly to providers using published contact information. No client information is handled by the Spoonfairies team. + +**For providers:** if you are looking for places to store client data, we recommend [CryptPad](https://cryptpad.fr/) which is a fully encrypted and privacy-conscious alternative to services like Google Drive. It offers 1GB of free storage, or further storage on subscription plans. + +
diff --git a/src/providers.njk b/src/providers.njk new file mode 100644 index 0000000..73cbbed --- /dev/null +++ b/src/providers.njk @@ -0,0 +1,24 @@ +--- +eleventyNavigation: + key: all providers + order: 1 +pagination: + data: collections.providers + size: 20 + alias: providerlist + reverse: true +title: providers +--- + +

all providers

+ +{% include "providerlist.njk" %} + +{% if pagination.href.previous or pagination.href.next %} + +{% endif %} diff --git a/src/providers/bex-m.md b/src/providers/bex-m.md new file mode 100644 index 0000000..dd35c0f --- /dev/null +++ b/src/providers/bex-m.md @@ -0,0 +1,34 @@ +--- +title: Bex M. +pronouns: vey/she +date: 2026-02-09 +tags: +- tutoring +- project management +- admin +- event planning +location: Phinney Ridge +contacts: +- title: fairy.lady [at] gmail [dot] com + href: mailto:fairy.lady@gmail.com?subject=Spoonfairies +--- + +## bio + +fox fairy with background in education, administration, and social work. + +## services + +- weekly check-in/project management services +- K-12 tutoring, particular expertise in English and physics +- administrative support (drafting, copy editing, scheduling, travel & event planning) + +### payment + +- sliding scale $30-50/hr, billable by quarter hour +- services swap/skill share +- pro bono option available as needed + +### time constraints + +5 hrs per week max (under current circumstances) diff --git a/src/providers/blythe-s.md b/src/providers/blythe-s.md new file mode 100644 index 0000000..277d41b --- /dev/null +++ b/src/providers/blythe-s.md @@ -0,0 +1,30 @@ +--- +title: Blythe S. +date: 2026-03-17 +pronouns: she/her +location: West Seattle +tags: +- hairdressing +- hygiene +contacts: +- title: glamouramalola [at] msn [dot] com + href: mailto:glamouramalola@msn.com?subject=Spoonfairies +- title: 206-910-8239 + href: tel:206-910-8239 +--- + +## bio + +I am an ally, friend and professional hairdresser. I am happiest when interacting with and learning about new people. I do my best to listen and observe as I get to know people. + +## services + +I can do haircutting and styling. I may be able to offer more if I learn of people’s different needs. I can also give personal hygiene products for those in need. + +### payment + +Pro bono + +### time constraints + +Appointment only, not available Monday eve or Sunday. diff --git a/src/providers/brooke-o.md b/src/providers/brooke-o.md new file mode 100644 index 0000000..4b096af --- /dev/null +++ b/src/providers/brooke-o.md @@ -0,0 +1,26 @@ +--- +title: Brooke O. +date: 2026-02-09 +pronouns: it/its +location: Vashon +tags: +- seamstress +- repair +- clothing +- mending +contacts: +- title: bsosment [at] gmail [dot] com + href: mailto:bsosment@gmail.com?subject=Spoonfairies +--- + +## bio + +I am a self-taught seamstress and fashion-minded punk. I have been stitching my jackets back together for as long as they've been falling apart, generally with a mind towards visible mending and eye-catching colors. + +## services + +Clothing/textile repair and upcycling, with a strong preference for jackets and/or heavier fabrics + +### payment + +cash/barter diff --git a/src/providers/lee-c.md b/src/providers/lee-c.md new file mode 100644 index 0000000..33bf728 --- /dev/null +++ b/src/providers/lee-c.md @@ -0,0 +1,37 @@ +--- +title: Lee C. +pronouns: ze/he +date: 2026-02-09 +tags: +- webdev +- web accessibility +- spreadsheets +- logos +- clothing +- art +- computers +- software +contacts: +- title: inherentlee.13 on signal + href: https://signal.me/#eu/PcJ86iNQeAbC-SFbxqI00gFQb6zL4Y6QDCsFDU2mokM4K40djsdNYa3hJAee79ll +- title: lee.cattarin [at] gmail [dot] com + href: mailto:lee.cattarin@gmail.com?subject=Spoonfairies +- title: leecat.art/contact + href: https://leecat.art/contact +--- + +## bio + +multidisciplinary artist and crafter. reluctant computer toucher. big fan of birds. + +## services + +web dev with a focus on accessibility, incl. accessibility reviews for your existing website. spreadsheets galore. basic logos, functional leatherwork, block printed clothing with existing designs or your own design (takes more work and resources, add'l cost). + +### payment + +sliding scale or skill swap + +### time constraints + +\*shrug emoji\* diff --git a/src/providers/providers.11tydata.js b/src/providers/providers.11tydata.js new file mode 100644 index 0000000..a4dae52 --- /dev/null +++ b/src/providers/providers.11tydata.js @@ -0,0 +1,6 @@ +export default { + tags: [ + "providers" + ], + "layout": "provider.njk" +}; diff --git a/src/providers/rain-v.md b/src/providers/rain-v.md new file mode 100644 index 0000000..2ffec24 --- /dev/null +++ b/src/providers/rain-v.md @@ -0,0 +1,29 @@ +--- +title: Rain V. +date: 2026-02-13 +pronouns: she/they +location: Redmond +tags: +- funds +- computers +- software +- errands +contacts: +- title: rainybean on discord +--- + +## bio + +I have many crafting hobbies such as woodworking and CNC, but I'm too busy and tired to have much time for them. such is life. I'm a software engineer by trade, living the corpo life I guess ᕕ( ᐛ )ᕗ + +## services + +mainly money tbh, and I can help with things if you're near Redmond or Bellevue and it doesn't take a lot of time. + +### payment + +praise? barter? (clean my place or body doubling with my partner Milo to help him sort and organize his stuff, little art commissions might be cool) or help someone else in this community for me ❤️ + +### time constraints + +1-2 hours per week, generally low availability so flexibility and planning ahead helps diff --git a/src/providers/roz-m.md b/src/providers/roz-m.md new file mode 100644 index 0000000..92d530b --- /dev/null +++ b/src/providers/roz-m.md @@ -0,0 +1,39 @@ +--- +title: Roz M. +date: 2026-02-09 +pronouns: she/her +location: Wallingford +tags: +- body doubling +- art +- mending +- admin +- medical advocate +contacts: +- title: rozmartinez [at] gmail [dot] com + href: mailto:rozmartinez@gmail.com?subject=Spoonfairies +- title: rozmartinezfineart.com + href: https://www.rozmartinezfineart.com/ +- title: rozmartinez.bsky.social on bsky + href: https://bsky.app/profile/rozmartinez.bsky.social +--- + +## bio + +Roz Martinez is a Seattle-based artist working predominantly in graphite and ink. She grew up on the east coast, learning how to express herself visually from her mother and grandmother, both of whom studied art extensively. + +## services + +- Body Doubling +- Art/Design: commissions, teaching, hosting art parties +- Mending/sewing +- Admin: email drafting, phone calls & scripting, desktop research +- Medical advocate/companion + +### payment + +Open to any upon negotiation + +### time constraints + +Can dedicate 1 day per week to Spoonfairies and other projects diff --git a/src/providers/template.md b/src/providers/template.md new file mode 100644 index 0000000..02c2690 --- /dev/null +++ b/src/providers/template.md @@ -0,0 +1,24 @@ +--- +eleventyExcludeFromCollections: true +permalink: false +title: template +date: 2026-02-01 +pronouns: +location: +tags: +contacts: +- title: example.1 on signal + href: https://signal.me +- title: 123-456-7890 + href: tel:123-456-7890 +- title: example [at] example [dot] com + href: mailto:example@example.com?subject=Spoonfairies +--- + +## bio + +## services + +### payment + +### time constraints diff --git a/src/service-pages.njk b/src/service-pages.njk new file mode 100644 index 0000000..4303ca7 --- /dev/null +++ b/src/service-pages.njk @@ -0,0 +1,35 @@ +--- +pagination: + data: collections.doublePagination + size: 1 + alias: tag +eleventyComputed: + permalink: /services/{{ tag.tagName | slugify }}/{% if tag.pageNumber %}{{ tag.pageNumber + 1 }}/{% endif %} + title: "providers tagged {{ tag.tagName }}" +--- + +

providers tagged {{ tag.tagName }}

+ +{% set providerlist = tag.pageData %} +{% include "providerlist.njk" %} + +{% if tag.pageSize != 1 %} + +{% endif %} diff --git a/src/services.njk b/src/services.njk new file mode 100644 index 0000000..e1b91fc --- /dev/null +++ b/src/services.njk @@ -0,0 +1,16 @@ +--- +eleventyNavigation: + key: all services + order: 2 +title: services +--- +

all services

+ +

Services are listed alphabetically.

+ +
    +{% for tag in collections | getKeys | removeBasicTags | sortAlphabetically %} + {% set tagUrl %}/services/{{ tag | slugify }}/{% endset %} +
  • {{ tag }}
  • + {% endfor %} +
diff --git a/src/src.11tydata.js b/src/src.11tydata.js index c5a2e34..6c08224 100644 --- a/src/src.11tydata.js +++ b/src/src.11tydata.js @@ -1,3 +1,3 @@ export default { - layout: "page.njk", + layout: "base.njk", }; diff --git a/src/team.md b/src/team.md new file mode 100644 index 0000000..1f2818e --- /dev/null +++ b/src/team.md @@ -0,0 +1,23 @@ +--- +title: team +--- + +# our team + +
+ +## core + +### organizer Bex + +Bex is an educator, social worker, and artist committed to creating a better world for queer and disabled people. Vey have been a Seattle renter since the early 2010s, dreaming and scheming more liberated futures for us all, while knitting socks and admiring the cutest kitties on the planet. + +email Bex about Spoonfairies + +### developer Lee + +Lee is a multidisciplinary artist and software engineer who works across many media. In the artistic space, ze creates block prints, leatherwork, handspun yarn, knits, and more; technologically, hir skills range from front-end web development with a focus on accessibility to back-end infrastructure and devOps. You can find Lee online at [leecat.art](https://leecat.art). + +email Lee about Spoonfairies + +