diff --git a/_blog/2020-05-01-issue-1.md b/_blog/2020-05-01-issue-1.md index 3dff2032..b469fe89 100644 --- a/_blog/2020-05-01-issue-1.md +++ b/_blog/2020-05-01-issue-1.md @@ -22,7 +22,7 @@ There’s no other way to say it: solidarity is a struggle. Today, on May Day, what can any of us do to help our fellow workers win their demands? It’s a complicated question for any of us, [even in our own neighborhoods](https://itsgoingdown.org/autonomous-groups-are-mobilizing-mutual-aid-initiatives-to-combat-the-coronavirus/). It’s one thing to share mask-wearing tips, [DIY PPE resources](https://diyppe.us/), or even a [list of global and US grants for artists](https://www.booooooom.com/2020/03/20/covid-19-resources-for-artists/). It’s another thing to commit to working through things, together, especially with distances and divides between our communities and workplaces. The Reveal’s recent [podcast](https://www.revealnews.org/episodes/pandemic-protests-and-profits/) on COVID-19 in Amazon warehouses quotes one worker as saying, “Until Amazon and Jeff Bezos starts realizing there's real people that are going to die in his warehouse, that's not going to stop. And we need the customers to speak up. We can't do it alone.” Customer boycotts are part of the fight to support Amazon warehouse workers, and solidarity from other workers goes a long way, too. -A handful of volunteer organizers in TWC have been talking with collectives of delivery and ride-hail drivers about ways to show our support and help one another. [Restarting this newsletter]({% link index.md %}) is one small way to organize ourselves in response. (You can subscribe [here](/subscribe)! But it’s not easy to pressure these powerful companies to treat their frontline workers better. One way tech workers and allies might be able to provide material support is by helping to simplify the process of [applying](https://www.wired.com/story/gig-workers-unemployment-benefits-wont-come-quickly/) for unemployment insurance. Another is to pressure tech companies – especially gig economy companies – to pay their workers what they’re owed, instead of allocating $110 million to fund a [counter-proposal](https://www.motherjones.com/coronavirus-updates/2020/04/protesting-uber-and-lyft-drivers-want-back-pay-and-more-coronavirus-protections/) that would 'guarantee' drivers [just $5.64/hr](https://laborcenter.berkeley.edu/the-uber-lyft-ballot-initiative-guarantees-only-5-64-an-hour/). +A handful of volunteer organizers in TWC have been talking with collectives of delivery and ride-hail drivers about ways to show our support and help one another. [Restarting this newsletter]({% link index.11ty.tsx %}) is one small way to organize ourselves in response. (You can subscribe [here](/subscribe)! But it’s not easy to pressure these powerful companies to treat their frontline workers better. One way tech workers and allies might be able to provide material support is by helping to simplify the process of [applying](https://www.wired.com/story/gig-workers-unemployment-benefits-wont-come-quickly/) for unemployment insurance. Another is to pressure tech companies – especially gig economy companies – to pay their workers what they’re owed, instead of allocating $110 million to fund a [counter-proposal](https://www.motherjones.com/coronavirus-updates/2020/04/protesting-uber-and-lyft-drivers-want-back-pay-and-more-coronavirus-protections/) that would 'guarantee' drivers [just $5.64/hr](https://laborcenter.berkeley.edu/the-uber-lyft-ballot-initiative-guarantees-only-5-64-an-hour/). Learning about how we’re all connected and building relationships to make positive change across the industry is a slow but necessary process. This is why we need to stay in the struggle, together. diff --git a/_data/press.yml b/_data/press.yml index 60a92ad3..0449ec17 100644 --- a/_data/press.yml +++ b/_data/press.yml @@ -149,7 +149,7 @@ date: 2018-03-01 - media: Peninsula Press — Stanford Journalism - title: Tech workers organize to resist Trump" + title: Tech workers organize to resist Trump url: https://peninsulapress.com/2017/11/06/tech-workers-organize-to-resist-trump date: 2017-11-06 diff --git a/_includes/blog.11ty.tsx b/_includes/blog.11ty.tsx new file mode 100644 index 00000000..4c2f97cf --- /dev/null +++ b/_includes/blog.11ty.tsx @@ -0,0 +1,45 @@ +import { Data, EleventyFuns } from "../types.ts"; + +export const render = async function ( + this: EleventyFuns, + data: Data & { include?: { limit?: number } }, +) { + const { + include: { limit } = {}, + page: { url }, + collections: { blog }, + } = data; + + const items = blog.toSorted((a, b) => -(a.date.getTime() - b.date.getTime())); + + const cards = await Promise.all( + items.slice(0, limit ?? items.length).map( + async (blog) => + ({ + type: "raw", + value: await this.renderFile("_includes/blog-card.html", { + ...data, + include: { blog }, + }), + }) as const, + ), + ); + + return url === "/blog/" ? ( + <> +

Blog

+ Explore our {items.length} blog posts +
+ <>{cards} +
+ + ) : ( + <> +

Blog Posts

+ {cards} + + See more blog posts + + + ); +}; diff --git a/_includes/blog.html b/_includes/blog.html deleted file mode 100644 index 9fe1e937..00000000 --- a/_includes/blog.html +++ /dev/null @@ -1,20 +0,0 @@ -{% assign limit = include.limit %} -{% assign sorted_blog = site.blog | filter_tags: include.tags | sort: 'date' | reverse %} - -{% if page.url == "/blog/" %} -

Blog

- Explore our {{ sorted_blog.size }} blog posts -
-{% else %} -

Blog Posts

-{% endif %} - -{% for blog in sorted_blog limit: limit %} - {% include blog-card.html blog=blog %} -{% endfor %} - -{% if page.url == "/blog/" %} -
-{% else %} - See more blog posts -{% endif %} diff --git a/_includes/press.11ty.tsx b/_includes/press.11ty.tsx new file mode 100644 index 00000000..a66fb61c --- /dev/null +++ b/_includes/press.11ty.tsx @@ -0,0 +1,45 @@ +import { DateTime } from "luxon"; + +import { Data, EleventyFuns } from "../types.ts"; + +export const render = async function ( + this: EleventyFuns, + { + include: { limit } = {}, + press, + site: { timeZone }, + berlin_press, + }: Data & { + include?: { limit?: number }; + }, +) { + const readDate = (x: string) => + DateTime.fromFormat(x, "yyyy-MM-dd").setZone(timeZone); + + const posts = [...press, ...berlin_press.filter((x) => x.lang === "en")].map( + ({ date, ...x }) => ({ ...x, date: readDate(date) }), + ); + posts.sort((a, b) => -(a.date.toUnixInteger() - b.date.toUnixInteger())); + + const icon = { + type: "raw", + value: await this.renderFile("_includes/icons/newspaper.html"), + }; + + return posts.slice(0, limit ?? posts.length).map((post) => ( +
+
{icon}
+
+
+ {post.media} —{" "} + +
+

+ {post.title} +

+
+
+ )); +}; diff --git a/_includes/press.html b/_includes/press.html deleted file mode 100644 index 4faa1ace..00000000 --- a/_includes/press.html +++ /dev/null @@ -1,23 +0,0 @@ -{% assign limit = include.limit %} -{% assign berlin_press = site.data.berlin_press | where:"lang",site.lang %} -{% assign posts = site.data.press | sort: 'date' | reverse %} -{% for post in posts limit: limit %} -
-
- {%- include icons/newspaper.html -%} -
-
-
- {{post.media}} — - -
-

- - {{ post.title }} - -

-
-
-{% endfor %} diff --git a/_layouts/event.11ty.tsx b/_layouts/event.11ty.tsx index 3b78ee05..c232a92b 100644 --- a/_layouts/event.11ty.tsx +++ b/_layouts/event.11ty.tsx @@ -1,13 +1,11 @@ import { DateTime } from "luxon"; -import { Page } from "../types.ts"; +import { EleventyFuns, Page } from "../types.ts"; export const data = { layout: "default.11ty.tsx" }; export const render = function ( - this: { - all_time_zones: (x: Date, timezones: string[]) => string; - }, + this: EleventyFuns, { content, title, @@ -53,7 +51,7 @@ export const render = function ( - {{ type: "raw", value: content }} + <>{{ type: "raw", value: content }} diff --git a/_layouts/newsletter.11ty.tsx b/_layouts/newsletter.11ty.tsx index 2d2aee07..a04d732b 100644 --- a/_layouts/newsletter.11ty.tsx +++ b/_layouts/newsletter.11ty.tsx @@ -5,25 +5,10 @@ import { select } from "hast-util-select"; import { toText } from "hast-util-to-text"; import { DateTime } from "luxon"; -import { Page, Site } from "../types.ts"; +import { BlogItem, Page, Site } from "../types.ts"; export const data = { layout: "default.11ty.tsx" }; -type BlogItem = { - data: { - image?: - | string - | { - file: string; - alt?: string; - }; - title: string; - }; - url: string; - date: Date; - content: string; -}; - const BlogCard = async ({ blog, timeZone, diff --git a/blog.11ty.tsx b/blog.11ty.tsx new file mode 100644 index 00000000..c3fb7ad0 --- /dev/null +++ b/blog.11ty.tsx @@ -0,0 +1,8 @@ +import { EleventyFuns } from "./types.ts"; + +export const render = async function (this: EleventyFuns, data: unknown) { + return { + type: "raw", + value: await this.renderFile("_includes/blog.11ty.tsx", data), + }; +}; diff --git a/blog.html b/blog.html deleted file mode 100644 index 27172d02..00000000 --- a/blog.html +++ /dev/null @@ -1 +0,0 @@ -{% include blog.html %} diff --git a/eleventy.config.js b/eleventy.config.js index 0137f39c..67b0aef6 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -1,5 +1,6 @@ import { pathToFileURL } from "node:url"; +import { RenderPlugin } from "@11ty/eleventy"; import { feedPlugin } from "@11ty/eleventy-plugin-rss"; import * as mdx from "@mdx-js/mdx"; import { toHtml } from "hast-util-to-html"; @@ -67,6 +68,8 @@ export default async (cfg) => { cfg.addDataExtension("yml", YAML.parse); cfg.addDataExtension("yaml", YAML.parse); + cfg.addPlugin(RenderPlugin); + const getRssConfig = (collection, name) => ({ type: "atom", outputPath: `/feed/${collection}.xml`, @@ -227,8 +230,13 @@ export default async (cfg) => { elementAttributeNameCase: "html", }); + const funs = this.config.javascriptFunctions; + return async function (data) { - const res = await mdxContent.call(this, data); + const res = await mdxContent({ + ...data, + eleventy: funs, + }); rehypeSlug({ slugify: slugifyKramdown, })(res); diff --git a/index.11ty.tsx b/index.11ty.tsx new file mode 100644 index 00000000..e5302136 --- /dev/null +++ b/index.11ty.tsx @@ -0,0 +1,89 @@ +import { EleventyFuns } from "./types.ts"; + +export const data = { + permalink: "/", +}; + +export const render = async function ( + this: EleventyFuns, + data: Record, +) { + return ( + <> +

+ Worker power in the{" "} + tech industry +

+ + {/* todo(maximsmol): add a banner/hero image to make this stand out even more */} +
+

+ Guided by our vision for an inclusive & equitable tech industry, TWC + organizes to build worker power through rank & file self-organization + and education. +

+

+ We are a coalition of workers in and around the tech industry, labor + organizers, community organizers, and friends. We work in solidarity + with existing movements towards social justice, workers' rights, and + economic inclusion. +

+

+ We’re a democratically structured, all-volunteer, and worker-led + organization. +

+
+ + +
+ {{ + type: "raw", + value: await this.renderFile("_includes/events.html", { + ...data, + include: { limit: 5 }, + }), + }} +
+ +
+ {{ + type: "raw", + value: await this.renderFile("_includes/blog.11ty.tsx", { + ...data, + include: { limit: 3 }, + }), + }} +
+ +
+

TWC in the Press

+ <> + {{ + type: "raw", + value: await this.renderFile("_includes/press.11ty.tsx", { + ...data, + include: { limit: 2 }, + }), + }} + + + + See more press mentions + +
+ + ); +}; diff --git a/index.md b/index.md deleted file mode 100644 index a8dbfb83..00000000 --- a/index.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -permalink: / ---- - -

Worker power in the tech industry

- - -
-

Guided by our vision for an inclusive & equitable tech industry, TWC organizes to build worker power through rank & file self-organization and education.

-

We are a coalition of workers in and around the tech industry, labor organizers, community organizers, and friends. - We work in solidarity with existing movements towards social justice, workers' rights, and economic inclusion.

-

We’re a democratically structured, all-volunteer, and worker-led organization.

-
- - -
- {% include events.html limit=5 %} -
- -
- {% include blog.html limit=3 %} -
- -
-

TWC in the Press

- {% include press.html limit=2%} - -See more press mentions - -
diff --git a/press.md b/press.mdx similarity index 57% rename from press.md rename to press.mdx index a456787a..3e43e5ae 100644 --- a/press.md +++ b/press.mdx @@ -2,8 +2,8 @@ title: Press --- -

{{title}}

+

{props.title}

If you’re a member of the press, please get in touch with us through press@techworkerscoalition.org. -{% include press.html %} +{{ type: "raw", value: await props.eleventy.renderFile("_includes/press.11ty.tsx", props) }} diff --git a/types.ts b/types.ts index a9fdc341..77d704b4 100644 --- a/types.ts +++ b/types.ts @@ -37,7 +37,44 @@ export type Site = { timeZone: string; }; +export type Press = { + media: string; + url: string; + title: string; + date: string; +}; + +export type BlogItem = { + data: { + image?: + | string + | { + file: string; + alt?: string; + }; + title: string; + }; + url: string; + date: Date; + content: string; +}; + export type Data = { chapters: Chapter[]; workplaces: Workplace[]; + berlin_press: (Press & { + lang: "en" | "de"; + byline: string; + })[]; + press: Press[]; + site: Site; + collections: { + blog: BlogItem[]; + }; + page: Page; +}; + +export type EleventyFuns = { + renderFile: (x: string, data?: unknown) => Promise; + all_time_zones: (x: Date, timezones: string[]) => string; };