From 01e746ac5fd79320f939a0f23584049f0d369070 Mon Sep 17 00:00:00 2001
From: Brooks Lybrand
Date: Wed, 17 Jan 2024 10:30:42 -0600
Subject: [PATCH] Refactor Conf Code (#153)
---
Dockerfile | 1 -
.../{conf.server.ts => conf2022.server.ts} | 58 +--
app/lib/conf2023.server.ts | 30 +-
app/routes/conf.2022._index.tsx | 6 +-
.../conf.2022._inner.schedule.may-25.tsx | 4 +-
...conf.2022._inner.speakers.$speakerSlug.tsx | 6 +-
app/routes/conf.2022._inner.workshops.tsx | 4 +-
app/routes/conf.2023._index.tsx | 7 +-
data/conf/2023/schedule.yaml | 89 -----
data/conf/2023/speakers.yaml | 345 ------------------
data/conf/2023/talks.yaml | 320 ----------------
11 files changed, 61 insertions(+), 809 deletions(-)
rename app/lib/{conf.server.ts => conf2022.server.ts} (74%)
delete mode 100644 data/conf/2023/schedule.yaml
delete mode 100644 data/conf/2023/speakers.yaml
delete mode 100644 data/conf/2023/talks.yaml
diff --git a/Dockerfile b/Dockerfile
index 442987d0..afbbfb51 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -47,7 +47,6 @@ WORKDIR /remixapp
COPY --from=production-deps /remixapp/node_modules /remixapp/node_modules
COPY --from=build /remixapp/build /remixapp/build
-COPY --from=build /remixapp/data /remixapp/data
COPY --from=build /remixapp/server.js /remixapp/server.js
COPY --from=build /remixapp/package.json /remixapp/package.json
COPY --from=build /remixapp/start.sh /remixapp/start.sh
diff --git a/app/lib/conf.server.ts b/app/lib/conf2022.server.ts
similarity index 74%
rename from app/lib/conf.server.ts
rename to app/lib/conf2022.server.ts
index ce02840c..43de8cc5 100644
--- a/app/lib/conf.server.ts
+++ b/app/lib/conf2022.server.ts
@@ -1,5 +1,3 @@
-import fsp from "fs/promises";
-import path from "path";
import invariant from "tiny-invariant";
import { processMarkdown } from "~/lib/md.server";
@@ -27,6 +25,11 @@ import {
sluggify,
} from "./conf";
+import speakersYamlFileContents from "../../data/conf/2022/speakers.yaml?raw";
+import sponsorsYamlFileContents from "../../data/conf/2022/sponsors.yaml?raw";
+import talksYamlFileContents from "../../data/conf/2022/talks.yaml?raw";
+import scheduleYamlFileContents from "../../data/conf/2022/schedule.yaml?raw";
+
let cache = new LRUCache<
string,
Array | Array | Array | Array
@@ -38,30 +41,13 @@ let cache = new LRUCache<
},
});
-const DATA_DIR = path.join(process.cwd(), "data");
-const CONF_ROOT_DIR = path.join(DATA_DIR, "conf");
-
-function getConfPaths(year: ConfYear) {
- let confDir = path.join(CONF_ROOT_DIR, String(year));
- return {
- speakersFile: path.join(confDir, "speakers.yaml"),
- sponsorsFile: path.join(confDir, "sponsors.yaml"),
- talksFile: path.join(confDir, "talks.yaml"),
- scheduleFile: path.join(confDir, "schedule.yaml"),
- };
-}
-
-type ConfYear = 2022 | 2023;
-
-export async function getSpeakers(year: ConfYear) {
- let cached = cache.get(`speakers-${year}`);
+export async function getSpeakers() {
+ let cached = cache.get("speakers");
if (isSpeakerArray(cached)) {
return cached;
}
- let { speakersFile: SPEAKERS_FILE } = getConfPaths(year);
- let speakersFileContents = await fsp.readFile(SPEAKERS_FILE, "utf8");
- let speakersRaw = yaml.parse(speakersFileContents);
+ let speakersRaw = yaml.parse(speakersYamlFileContents);
let speakers: Array = [];
for (let speakerRaw of speakersRaw) {
let { html: bioHTML } = await processMarkdown(speakerRaw.bio);
@@ -86,15 +72,13 @@ export async function getSpeakers(year: ConfYear) {
return speakers;
}
-export async function getSponsors(year: ConfYear) {
- let cached = cache.get(`sponsors-${year}`);
+export async function getSponsors() {
+ let cached = cache.get("sponsors");
if (isSponsorArray(cached)) {
return cached;
}
- let { sponsorsFile: SPONSORS_FILE } = getConfPaths(year);
- let sponsorsFileContents = await fsp.readFile(SPONSORS_FILE, "utf8");
- let sponsorsRaw = yaml.parse(sponsorsFileContents);
+ let sponsorsRaw = yaml.parse(sponsorsYamlFileContents);
let sponsors: Array = [];
for (let sponsorRaw of sponsorsRaw) {
invariant(
@@ -110,15 +94,13 @@ export async function getSponsors(year: ConfYear) {
return sponsors;
}
-export async function getTalks(year: ConfYear) {
- let cached = cache.get(`talks-${year}`);
+export async function getTalks() {
+ let cached = cache.get("talks");
if (isTalkArray(cached)) {
return cached;
}
- let { talksFile: TALKS_FILE } = getConfPaths(year);
- let talksFileContents = await fsp.readFile(TALKS_FILE, "utf8");
- let talksRaw = yaml.parse(talksFileContents);
+ let talksRaw = yaml.parse(talksYamlFileContents);
let talks: Array = [];
for (let talkRaw of talksRaw) {
invariant(
@@ -138,18 +120,16 @@ export async function getTalks(year: ConfYear) {
return talks;
}
-export async function getSchedule(year: ConfYear) {
- let cached = cache.get(`schedule-${year}`);
+export async function getSchedule() {
+ let cached = cache.get("schedule");
if (isScheduleItemArray(cached)) {
return cached;
}
- let { scheduleFile: SCHEDULE_FILE } = getConfPaths(year);
- let allTalks = await getTalks(year);
- let allSpeakers = await getSpeakers(year);
+ let allTalks = await getTalks();
+ let allSpeakers = await getSpeakers();
- let schedulesFileContents = await fsp.readFile(SCHEDULE_FILE, "utf8");
- let scheduleItemsRaw = yaml.parse(schedulesFileContents);
+ let scheduleItemsRaw = yaml.parse(scheduleYamlFileContents);
let scheduleItems: Array = [];
for (let scheduleItemRaw of scheduleItemsRaw) {
diff --git a/app/lib/conf2023.server.ts b/app/lib/conf2023.server.ts
index 32e79526..54c453c4 100644
--- a/app/lib/conf2023.server.ts
+++ b/app/lib/conf2023.server.ts
@@ -1,10 +1,13 @@
import LRUCache from "lru-cache";
import { DateTime } from "luxon";
+import yaml from "yaml";
+import invariant from "tiny-invariant";
import {
sluggify,
validateSessionizeSessionData,
validateSessionizeSpeakerData,
} from "./conf2023";
+import sponsorsYamlFileContents from "../../data/conf/2023/sponsors.yaml?raw";
import type {
Speaker,
SpeakerSession,
@@ -13,6 +16,8 @@ import type {
SessionizeSpeakerData,
SessionizeSessionData,
} from "./conf2023";
+import type { Sponsor } from "./conf";
+import { isSponsor, isSponsorArray } from "./conf";
const CONF_TIME_ZONE = "America/Denver";
const NO_CACHE =
@@ -20,13 +25,14 @@ const NO_CACHE =
const SPEAKERS_CACHE_KEY = "speakers";
const SESSIONS_CACHE_KEY = "sessions";
const SCHEDULES_CACHE_KEY = "schedules";
+const SPONSORS_CACHE_KEY = "schedules";
const SESSIONIZE_ENDPOINT = "https://sessionize.com/api/v2/s8ds2hnu";
const SESSIONIZE_API_DETAILS_URL =
"https://sessionize.com/app/organizer/schedule/api/endpoint/9617/7818";
let cache = new LRUCache<
"speakers" | "sessions" | "schedules",
- (Speaker | SpeakerSession | Schedule)[]
+ (Speaker | SpeakerSession | Schedule | Sponsor)[]
>({
max: 250,
maxSize: 1024 * 1024 * 12, // 12 mb
@@ -495,3 +501,25 @@ async function fetchNaiveStaleWhileRevalidate(
});
}
}
+
+export async function getSponsors() {
+ let cached = cache.get(SPONSORS_CACHE_KEY);
+ if (isSponsorArray(cached)) {
+ return cached;
+ }
+
+ let sponsorsRaw = yaml.parse(sponsorsYamlFileContents);
+ let sponsors: Array = [];
+ for (let sponsorRaw of sponsorsRaw) {
+ invariant(
+ isSponsor(sponsorRaw),
+ `Sponsor ${JSON.stringify(
+ sponsorRaw,
+ )} is not valid. Please check the sponsors file.`,
+ );
+ sponsors.push(sponsorRaw);
+ }
+ cache.set(SPONSORS_CACHE_KEY, sponsors);
+
+ return sponsors;
+}
diff --git a/app/routes/conf.2022._index.tsx b/app/routes/conf.2022._index.tsx
index befd1511..3c83026b 100644
--- a/app/routes/conf.2022._index.tsx
+++ b/app/routes/conf.2022._index.tsx
@@ -7,7 +7,7 @@ import { OutlineButtonLink, primaryButtonLinkClass } from "~/ui/buttons";
import "~/styles/index.css";
import { Fragment } from "react";
import type { Sponsor, Speaker } from "~/lib/conf";
-import { getSpeakers, getSponsors } from "~/lib/conf.server";
+import { getSpeakers, getSponsors } from "~/lib/conf2022.server";
import { Link } from "~/ui/link";
import { CACHE_CONTROL } from "~/lib/http.server";
@@ -35,7 +35,7 @@ export const meta: MetaFunction = (args) => {
};
export const loader = async ({ request }: LoaderFunctionArgs) => {
- const speakersOrdered = await getSpeakers(2022);
+ const speakersOrdered = await getSpeakers();
const speakersShuffled = speakersOrdered
// save a bit of data by not sending along the bio to the home page
.map(
@@ -47,7 +47,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
)
.sort(() => Math.random() - 0.5);
- const allSponsors = await getSponsors(2022);
+ const allSponsors = await getSponsors();
const sponsors = {
premier: allSponsors.find((s) => s.level === "premier"),
gold: allSponsors
diff --git a/app/routes/conf.2022._inner.schedule.may-25.tsx b/app/routes/conf.2022._inner.schedule.may-25.tsx
index 2f2848f4..f7c77155 100644
--- a/app/routes/conf.2022._inner.schedule.may-25.tsx
+++ b/app/routes/conf.2022._inner.schedule.may-25.tsx
@@ -3,7 +3,7 @@ import { json } from "@remix-run/node";
import { Link, useLoaderData } from "@remix-run/react";
import type { MetaFunction } from "@remix-run/react";
import { metaV1 } from "@remix-run/v1-meta";
-import { getSchedule } from "~/lib/conf.server";
+import { getSchedule } from "~/lib/conf2022.server";
import { CACHE_CONTROL } from "~/lib/http.server";
import { sluggify } from "~/lib/conf";
@@ -17,7 +17,7 @@ export const meta: MetaFunction = (args) => {
type LoaderData = { scheduleItems: Awaited> };
export const loader: LoaderFunction = async () => {
- const scheduleItems = await getSchedule(2022);
+ const scheduleItems = await getSchedule();
return json(
{ scheduleItems },
{ headers: { "Cache-Control": CACHE_CONTROL.DEFAULT } },
diff --git a/app/routes/conf.2022._inner.speakers.$speakerSlug.tsx b/app/routes/conf.2022._inner.speakers.$speakerSlug.tsx
index 4f622d1e..3657aabd 100644
--- a/app/routes/conf.2022._inner.speakers.$speakerSlug.tsx
+++ b/app/routes/conf.2022._inner.speakers.$speakerSlug.tsx
@@ -9,7 +9,7 @@ import {
import type { MetaFunction } from "@remix-run/react";
import { json } from "@remix-run/node";
import { metaV1 } from "@remix-run/v1-meta";
-import { getSpeakers, getTalks } from "~/lib/conf.server";
+import { getSpeakers, getTalks } from "~/lib/conf2022.server";
import "~/styles/conf-speaker.css";
import { sluggify } from "~/lib/conf";
import { CACHE_CONTROL } from "~/lib/http.server";
@@ -34,8 +34,8 @@ export const meta: MetaFunction = (args) => {
export const loader = async ({ params }: LoaderFunctionArgs) => {
const [allTalks, allSpeakers] = await Promise.all([
- getTalks(2022),
- getSpeakers(2022),
+ getTalks(),
+ getSpeakers(),
]);
const speaker = allSpeakers.find((s) => s.slug === params.speakerSlug);
if (!speaker) throw new Response("Speaker not found", { status: 404 });
diff --git a/app/routes/conf.2022._inner.workshops.tsx b/app/routes/conf.2022._inner.workshops.tsx
index f5245f86..5e0bee88 100644
--- a/app/routes/conf.2022._inner.workshops.tsx
+++ b/app/routes/conf.2022._inner.workshops.tsx
@@ -42,7 +42,7 @@ export default function Workshops() {
href="https://twitter.com/kentcdodds"
>
@@ -53,7 +53,7 @@ export default function Workshops() {
href="https://twitter.com/ryanflorence"
>
diff --git a/app/routes/conf.2023._index.tsx b/app/routes/conf.2023._index.tsx
index a67d2efd..90d5d1e7 100644
--- a/app/routes/conf.2023._index.tsx
+++ b/app/routes/conf.2023._index.tsx
@@ -10,11 +10,10 @@ import {
} from "~/ui/buttons";
import "~/styles/index.css";
import { Fragment } from "react";
-import { getSponsors } from "~/lib/conf.server";
import type { Sponsor, SponsorLevel } from "~/lib/conf";
import { Link } from "~/ui/link";
import { CACHE_CONTROL } from "~/lib/http.server";
-import { getSpeakers } from "~/lib/conf2023.server";
+import { getSpeakers, getSponsors } from "~/lib/conf2023.server";
import type { Speaker } from "~/lib/conf2023";
export const meta: MetaFunction = (args) => {
@@ -50,7 +49,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
console.error(err);
}
- let allSponsors = await getSponsors(2023);
+ let allSponsors = await getSponsors();
let sponsors: Partial> = {};
for (let sponsor of allSponsors.sort(randomSort)) {
let level = sponsor.level;
@@ -149,7 +148,7 @@ function EarlySponsors() {
-
+
diff --git a/data/conf/2023/schedule.yaml b/data/conf/2023/schedule.yaml
deleted file mode 100644
index ff4e4bc1..00000000
--- a/data/conf/2023/schedule.yaml
+++ /dev/null
@@ -1,89 +0,0 @@
-- time: 7:30 AM
- title: Breakfast & Registration 🍞 🥚 🥞 🍳 🍵 🥣 🥓 🍩
- content:
- A delicious hot breakfast is hosted in the hotel next to the conference
- room. If you didn't register the day before, now's the time to get your swag
- bag and lanyard!
-
-- time: 9:00 AM
- title: Opening Remarks
- content: Ceora will get us oriented on important logistics for the conference.
- speakers:
- - Ceora Ford
-
-- time: 9:10 AM
- talk: Keynote
-
-- time: 9:35 AM
- talk: How To WebPageTest
-
-- time: 10:00 AM
- talk: "Instantaneously Interactive: Remix as a Browser Framework"
-
-- time: 10:25 AM
- talk: State Machines On The Edge
-
-- time: 10:50 AM
- title: ☕ Morning Break
- content:
- These breaks are extra long to give you time to visit with other attendees!
- Take advantage of that!
-
-- time: 11:15 AM
- talk: Remixing Hydrogen
-
-- time: 11:40 AM
- talk: Deno and Remix
-
-- time: 12:05 PM
- talk: Remix 3D Blast
-
-- time: 12:10 PM
- talk: "Web Vitals: The importance of measuring a user great web experience"
-
-- time: 12:15 PM
- talk: Making slow responses seem fast with stale-while-revalidate
-
-- time: 12:20 PM
- title:
- Lunch 🥪 🌮 🥘 🍣 🥗 🍐 🌯 🥒 🍝 🌭 🥩 🍜 🦐 🥨 🥟 🍕 🥙 🍔 🍚 🍱 🍛 🍲 🍢
- content:
- You'll get a pre-paid card and directions to various local restaurants. The
- lunch break is extra long so you can take the opportunity to get to know
- other attendees (and to give you time to get to and from a local restaurant
- to enjoy). Take advantage of the time! But make it back for the afternoon of
- talks.
-
-- time: 2:25 PM
- talk: Building tech for social good with low-code tools
-
-- time: 2:30 PM
- talk: Expanding Remix with Rust
-
-- time: 2:35 PM
- talk: "Full Stack Fast: Data on the Edge"
-
-- time: 2:45 PM
- talk: Remix your UI & UX to another level
-
-- time: 3:10 PM
- talk: Magically create forms + actions with Remix Forms
-
-- time: 3:35 PM
- talk: Incremental Remix
-
-- time: 4:00 PM
- title: ☕ Afternoon Break
- content: This is the last break of the day. Take some deep breaths!
-
-- time: 4:25 PM
- talk: Outstanding Search Experiences with Remix and Algolia
-
-- time: 4:50 PM
- talk: Switching to Remix at Neighbor
-
-- time: 5:15 PM
- title: Closing Remarks
- content: Ceora will help us wrap and thank you for coming!
- speakers:
- - Ceora Ford
diff --git a/data/conf/2023/speakers.yaml b/data/conf/2023/speakers.yaml
deleted file mode 100644
index 2f933175..00000000
--- a/data/conf/2023/speakers.yaml
+++ /dev/null
@@ -1,345 +0,0 @@
-- name: "Ryan Dahl"
- linkText: "@ry"
- link: "https://github.com/ry"
- title: "CEO, Deno + Creator of Node.js"
- imgSrc: "/conf-images/speakers/ryan.jpg"
- bio: >-
- In 2009, Ryan Dahl released [Node.js](https://nodejs.org/). Now, Ryan is the
- CEO of [Deno](https://deno.com/), the company behind [the Deno
- project](https://deno.land): A modern runtime for JavaScript and TypeScript.
- [Deno's deploy product](https://deno.com/deploy) is pushing this runtime in
- the future of modern web architecture via multi-regional deploys with an
- outrageously fast runtime.
-
-- name: "Shaundai Person"
- linkText: "@shaundai"
- link: "https://twitter.com/shaundai"
- title: "Senior Software Engineer, Netflix"
- imgSrc: "/conf-images/speakers/shaundai.jpg"
- bio: >-
- Shaundai is a Senior Software Engineer (Netflix) and educator based in
- Atlanta, GA, US. She is passionate about making programming interesting and
- approachable for all, and does that through her work as a course instructor
- ([tsforjs.com](https://www.tsforjs.com/)), co-lead for React Robins
- ([reactrobins.com](https://www.reactrobins.com/)), and [technical
- blogger](https://blog.shaundai.com/).
-
-
- In her spare time, Shaundai loves to go hiking, jogging, and listen to
- audiobooks. Find her on Twitter at
- [@shaundai](https://twitter.com/shaundai).
-
-- name: "Anthony Frehner"
- linkText: "@frehner_a"
- link: "https://twitter.com/frehner_a"
- title: "Senior Software Engineer at Shopify"
- imgSrc: "/conf-images/speakers/anthony.jpg"
- bio: >-
- Anthony Frehner is a frontend web developer and architect. He likes to
- contribute to open source when he has the time! Anthony is currently working
- on [Hydrogen](https://hydrogen.shopify.dev/) 🙂
-
-
- Anthony's recently been providing feedback on a [WICG
- proposal](https://github.com/WICG/app-history) for which he also spent some
- time making a [polyfill](https://github.com/frehner/appHistory). He's a
- core-team member of the [single-spa](https://single-spa.js.org) open source
- library, he occasionally give conference talks–here's Anthony's talk at
- [React Rally 2019](https://youtu.be/RgqSlRbbvwA)–and [write technical
- articles](https://dev.to/frehner), and he proposed a new CSS unit called
- [vhc](https://github.com/w3c/csswg-drafts/issues/4329) which eventually
- turned into the [`dvh`, `lvh`, and
- `svh`](https://dev.to/frehner/css-vh-dvh-lvh-svh-and-vw-units-27k4) (and
- equivalent `*vw`) CSS units, which was [very
- exciting](https://twitter.com/frehner_a/status/1405915191582380041) for him
- personally!
-
-- name: "Michael Jackson"
- linkText: "@mjackson"
- link: "https://twitter.com/mjackson"
- title: "Co-Founder & CEO, Remix"
- imgSrc: "/m.jpg"
- bio: >-
- Michael Jackson is the CEO and co-creator/co-founder of
- [Remix](https://remix.run). He is the co-author of [React
- Router](https://reactrouter.com/) and a [prolific contributor to open
- source](https://github.com/mjackson). He is the creator of
- [unpkg.com](https://unpkg.com) and gets a kick out of discussing distributed
- system design as much as he enjoys front-end architecture. Michael lives in
- Carlsbad, CA with his wife, two boys, and two girls.
-
-- name: "Ceora Ford"
- type: "emcee"
- linkText: "@ceeoreo_"
- link: "https://twitter.com/ceeoreo_"
- title: "Developer Advocate, Apollo"
- imgSrc: "/conf-images/speakers/ceora.jpg"
- bio: >-
- Ceora is a developer advocate based in Philadelphia. Her career thus far has
- centered around creating educational content focused on making the tech
- industry more accessible to everyone. She's been able to work with amazing
- companies like [CodeSandbox](https://codesandbox.com),
- [DigitalOcean](https://digitalocean.com), [egghead.io](https://egghead.io),
- and [Apollo GraphQL](https://www.apollographql.com) and has recently joined
- [the Stack Overflow Podcast](https://stackoverflow.blog/podcast) as a host.
- Outside of tech, she spends way too much time watching anime, listening to
- K-pop, and attempting to play the guitar.
-
-- name: "Sébastien Morel"
- linkText: "@sebastienmorel"
- link: "https://www.linkedin.com/in/sebastienmorel"
- title: "Chief Technology Officer at Crystallize"
- imgSrc: "/conf-images/speakers/sebastien.jpg"
- bio: >-
- Sébastien is a passionate and accomplished tech leader and problem-solver
- with extensive experience in architecture, performance optimizations,
- development, and system administration. CTO at Crystallize, a super-fast,
- super modern, super sexy, and super-powerful Headless eCommerce"", he's in
- charge (among other) of the Developer eXperience initiative.
-
-
- Previously, he led and grew his former web agency for 18 years working on
- more than 150 projects successfully and proudly implemented, deployed and
- maintained. Agnostic of the web technology he's using, Sébastien is also an
- open source maintainer active in the PHP/Symfony community.
-
-- name: "Arisa Fukuzaki"
- linkText: "@arisa_dev"
- link: "https://twitter.com/arisa_dev"
- title: "DevRel Engineer at Storyblok"
- imgSrc: "/conf-images/speakers/arisa.jpg"
- bio: >-
- Arisa is a DevRel Engineer at Storyblok & an organizer of a free tech skill
- & knowledge-sharing community, Lilac. Her mission is to learn, speak,
- connect and help. In her private time, she is a podcaster, an Aikido
- fighter, and a GirlCode ambassador.
-
-- name: "Greg Brimble"
- linkText: "@GregBrimble"
- link: "https://twitter.com/GregBrimble"
- title: "Systems Engineer at Cloudflare"
- imgSrc: "/conf-images/speakers/greg.jpg"
- bio: >-
- Greg is a Systems Engineer at [Cloudflare](https://www.cloudflare.com/)
- working on [Cloudflare Pages](https://pages.cloudflare.com/) in the Emerging
- Technologies and Incubation department. Cloudflare Pages is a full-stack
- developer platform and [they were very excited to add support for Remix at
- the end of last
- year](https://blog.cloudflare.com/remix-on-cloudflare-pages/).
-
-
- Before Pages, Greg worked with Cloudflare's Speed Team where he learned to
- appreciate the Network tab of DevTools. Greg has also contributed to the Web
- Almanac and numerous open-source projects, and, most importantly, he has his
- fingers crossed for enough snow to go [skiing after Remix
- Conf](https://remix.run/conf/schedule/may-26)! ⛷
-
-- name: "Nick Small"
- linkText: "nickjs.com"
- link: "https://nickjs.com"
- title: "JavaScript Developer"
- imgSrc: "/conf-images/speakers/nick.jpg"
- bio: >-
- Nick is a long-time dev of many disciplines: JavaScript, full-stack, native,
- operating systems, game dev. He's motivated by improving people's lives by
- finding really bad software in consequential places and making it better.
- Nick's been an early employee at mission-driven companies like Shopify and
- Devoted Health; empowered citizens and civil servants at US Digital Service,
- Defense Digital Service, and the NATO mission in Afghanistan; and
- volunteered on projects to strengthen democracy and build municipal Open
- Data pipelines.
-
-
- These days Nick lives in the mountains with his wife and kids, and he's
- focused on tooling to let more people write more accessible software with
- fewer bugs. Go Remix. Active hobbies include: constructing crosswords
- (poorly), flying planes (successfully) (so far), building better houses
- (fingers crossed).
-
-- name: "Scott Smerchek"
- linkText: "@smerchek"
- link: "https://twitter.com/smerchek"
- title: "Software Engineer at UDisc"
- imgSrc: "/conf-images/speakers/scott.jpg"
- bio: >-
- Scott's a software engineer with over a decade of experience building web
- applications for healthcare enterprises from frontend, to APIs, and even
- infrastructure. Now Scott works at UDisc, a quickly growing disc golf
- company that is pushing the sport forward through technology. Scott's always
- favored working in the backend, but Remix is helping him to enjoy working
- across the full stack, once again. He's incredibly excited about the future
- of building web applications with Remix and the ease of deploying to the
- modern edge hosting providers.
-
-- name: "Erick Tamayo"
- linkText: "@ericktamayo"
- link: "https://twitter.com/ericktamayo"
- title: "Senior Web Developer at Shopify"
- imgSrc: "/conf-images/speakers/erick.jpg"
- bio: >-
- Erick Tamayo was born in the Dominican Republic. He currently lives in
- Calgary Canada with his family. Erick's currently developing Metronome which
- is a tool for Real User Monitoring (RUM) specifically for Remix. He's been
- following Remix since 2020 and decided to join the community in 2021. Since
- then he's loved everything about Remix and its community!
-
-- name: "Ben Wishovich"
- linkText: "@iambenwis"
- link: "https://twitter.com/iambenwis"
- title: "Full Stack Web Dev"
- imgSrc: "/conf-images/speakers/ben.jpg"
- bio: >-
- Ben is a full stack web developer and software quality engineer with
- experience building high performance web applications. He's excited about
- using Remix and Rust to expand the possibilities and performance of the web
- app. When not coding, Ben might be found running around outside, cooking, or
- reading sci-fi in the sunny SF Bay Area.
-
-- name: "Vic Vijayakumar"
- linkText: "@VicVijayakumar"
- link: "https://twitter.com/VicVijayakumar"
- title: "Staff engineer at Eventbrite"
- imgSrc: "/conf-images/speakers/vic.jpg"
- bio: >-
- Vic is a Staff Engineer @ Eventbrite and indie software maker from Raleigh,
- North Carolina. He's a dad, runner, violinist, and is severely addicted to
- acquiring new hobbies. He has run the tech side of North Carolina's
- extremely popular Rare & Vintage Beer Festival for the last 10 years.
-
-
- Vic was previously in the scientific communications space and a technical
- cofounder of the Research Square platform, an inaugural recipient of the
- Fast Company "Brands that Matter" list for accelerating research
- communication during the pandemic.
-
-
- In his spare time, you can find Vic building LEGO with his family or out at
- the plant nursery adopting yet another plant.
-
-- name: "Daniel Weinmann"
- linkText: "@danielweinmann"
- link: "https://twitter.com/danielweinmann"
- title: "Founder and CEO at Seasoned"
- imgSrc: "/conf-images/speakers/daniel.jpg"
- bio: >-
- In order to bring his startups to life, Daniel had to go through a 9-year
- journey to become the technical founder and CTO he needed in his teams.
- However, his real passion has always been the non-technical way, and having
- to spend his days coding took a toll on him.
-
-
- When Daniel was finally able to come back to the business side, he had a
- secret weapon: in his struggles to leave the technical life behind, he
- gained a deep understanding of what it takes for a non-technical founder to
- create successful startups.
-
-
- Beyond his own journey, he's helped tons of founders build world-class
- products over the last 20+ years. Along the way, he was CEO, CMO, and CTO of
- many startups. Daniel has also founded a few successful ones himself,
- including Mailee, which was sold to a Brazilian internet provider, and
- Catarse, the biggest crowdfunding platform in Latin America.
-
-- name: "Sarah Dayan"
- linkText: "@frontstuff_io"
- link: "https://twitter.com/frontstuff_io"
- title: "Staff Software Engineer at Algolia"
- imgSrc: "/conf-images/speakers/sarah.jpg"
- bio: >-
- Sarah is a Staff Software Engineer from Paris, France who works on front-end
- search experiences at Algolia.
-
-
- She created the [Dinero.js](https://github.com/dinerojs/dinero.js) monetary
- library and hosts the [Developer
- Experience](https://developerexperience.buzzsprout.com/) podcast show. She's
- passionate about building dynamic front-end experiences, and won't shut up
- about TDD and utility-first CSS. She shares what she learns on [her
- blog](https://frontstuff.io/) and at tech conferences around the world.
-
-- name: "Erik Rasmussen"
- linkText: "@erikras"
- link: "https://twitter.com/erikras"
- title: "Software Engineer at Centered"
- imgSrc: "/conf-images/speakers/erik.jpg"
- bio: >-
- Erik is an expat American living in Spain. He's the author of Redux Form and
- Final Form, and is currently in love with TypeScript, XState, and Remix. His
- day job is using those technologies to build Centered.app, a tool to combat
- the Twitters' and Facebooks' attempts to steal your attention, and give it
- back to you to be more productive in your work.
-
-- name: "Dennis Beatty"
- linkText: "@dnsbty"
- link: "https://twitter.com/dnsbty"
- title: "Senior Software Engineer at Neighbor"
- imgSrc: "/conf-images/speakers/dennis.jpg"
- bio: >-
- Dennis works as a senior software engineer at Neighbor, a marketplace for
- self-storage, where he led the switch to Remix. While Dennis works across
- the entire tech stack, he's especially comfortable with systems architecture
- and seeing how pieces fit together. He's contributed to [open
- source](https://github.com/dnsbty) software in various ways (mostly within
- the Elixir ecosystem) and has enjoyed sharing some of his learning on [his
- blog](https://dennisbeatty.com) and [his Youtube
- channel](https://www.youtube.com/channel/UC9l_1J8y_au9Nlgrfz0rduw). Outside
- of programming Dennis loves spending time with his wife and his daughter who
- was born this past year, and he also skis, explores Utah's national forests,
- and shoots photos of the stars.
-
-- name: "Jon Jensen"
- linkText: "@jenseng"
- link: "https://twitter.com/jenseng"
- title: "Senior Software Engineer at Netflix"
- imgSrc: "/conf-images/speakers/jon.jpg"
- bio: >-
- Jon is a Senior Software Engineer (Netflix) working to improve the developer
- experience for other UI engineers. Previously he worked at Amazon and
- Instructure working on various things software-y. In his spare time, he's
- usually in the mountains, playing Minecraft with his kids, or following the
- Red Food Truck around SLC.
-
-- name: "Henri Helvetica"
- linkText: "@HenriHelvetica"
- link: "https://twitter.com/HenriHelvetica"
- title: "Software Engineer at Catchpoint Systems"
- imgSrc: "/conf-images/speakers/henri.jpg"
- bio: >-
- Henri is a developer who has turned his interests to a passionate mix of
- site performance engineering and pinches of user experience, which led to
- his joining Catchpoint Systems on the WebPageTest Team. When not reading the
- deluge of daily research docs and case studies, or profiling sites in his
- favourite tools, Henri can be found contributing back to the community:
- Toronto Web Performance Group meetup + Jamstack Toronto organizer, curating
- conference content or volunteering his time for lunch and learns at various
- bootcamps. Otherwise, Henri is focusing on running the fastest 5k possible
- (surprise surprise), encouraging a healthy lifestyle via `#devsWhoRun`.
-
-- name: "Emily Kauffman"
- linkText: "@intrepid_em"
- link: "https://twitter.com/intrepid_em"
- title: "Lead Software Engineer at Harvie"
- imgSrc: "/conf-images/speakers/emily.png"
- bio: >-
- Emily is a Lead Software Engineer based out of Pittsburgh, PA. She's a
- lifelong learner, adjunct professor, and IoT enthusiast. Emily has a tech
- background in healthcare, robotics, and more recently, bringing local food
- to the masses at [Harvie](https://www.harvie.farm). In her spare time, you
- can find Emily tinkering with her homemade conversion van, scuba diving, or
- trying her hand at landscape photography.
-
-- name: "Aaron K Saunders"
- linkText: "@aaronksaunders"
- link: "https://twitter.com/aaronksaunders"
- title: "Founder & CEO of Clearly Innovative"
- imgSrc: "/conf-images/speakers/aaron.jpg"
- bio: >-
- Aaron is an Information Technology Strategist, Thought Leader, and Diversity
- and Inclusion Trailblazer - Founder & CEO of Clearly Innovative. He believes
- technology and in his case coding is an enabler and an equalizer. Aaron has
- focused a large part of his career training and developing individuals who
- want to get into tech but cannot find the opening; through the
- apprenticeship program he ran at Clearly Innovative, teaching web and mobile
- development at Howard University, and the free technical videos on his
- Youtube Channel he just want to help others get a seat at the table of tech
- and innovation.
diff --git a/data/conf/2023/talks.yaml b/data/conf/2023/talks.yaml
deleted file mode 100644
index 0c14b168..00000000
--- a/data/conf/2023/talks.yaml
+++ /dev/null
@@ -1,320 +0,0 @@
-- title: Keynote
- time: 9:10 AM
- type: regular
- description: Michael will kick the inaugural Remix Conference off!
- speakers:
- - Michael Jackson
-
-- title: "Instantaneously Interactive: Remix as a Browser Framework"
- time: 10:00 AM
- type: regular
- description: >-
- Your Remix app is so performant that–even without a solid internet
- connection–navigation on your site seems to happen almost instantaneously.
- Whether rendered on the client side or server side, pages load data quickly
- and all the information you users are interested in is on the screen without
- the wait. But why?
-
-
- In this talk, we discuss the optimizations in Remix for data fetching and
- rendering apps in the browser that enhance both the user experience and
- developer experience.
-
- speakers:
- - Shaundai Person
-
-- title: "State Machines On The Edge"
- time: 10:25 AM
- type: regular
- description: >-
- Modeling business logic with state machines has numerous benefits, from
- eliminating bugs caused by impossible states to visualizing the logic to
- communicate with non-technical shareholders to simply communicating user
- flow between technical colleagues. In this talk, I'm going to demonstrate,
- via live coding, how to combine the strengths of Remix and XState to create
- a checkout flow entirely on the backend. No. JavaScript. Required.
- speakers:
- - Erik Rasmussen
-
-- title: Remixing Hydrogen
- time: 11:15 AM
- type: regular
- description: >-
- Let's talk about some of the headaches of building headless Shopify
- e-commerce stores, and how Hydrogen-UI + Remix make it better. Pre-built
- Shopify components? Check. GraphQL auto-completion? Oh yeah. Speedy
- websites? Blazing fast.
- speakers:
- - Anthony Frehner
-
-- title: Deno and Remix
- time: 11:40 AM
- type: regular
- description: >-
- In this talk Ryan will give an overview of Deno, a modern JavaScript
- runtime, and Deno Deploy, a serverless at edge JavaScript hosting service.
- He'll give a peak behind the sceenes at the technology powering Deno Deploy,
- and of course demo how to deploy a Remix app on it.
- speakers:
- - Ryan Dahl
-
-- title: Remix 3D Blast
- time: 12:05 PM
- type: lightning
- description: >-
- Whether you want to progressively enhance a traditional website or build an
- immersive 3D experience, Remix gives us a powerful and fun framework to
- create with WebGL and three.js. After deploying a 3D Remix experience to
- production, I've found that all the patterns that Remix provides are just as
- valuable even when we're not rendering to the DOM. In this talk, I'll show
- off some zany 3D antics to explain how Remix and react-three-fiber can work
- together to help you build fantastic experiences for your users.
-
-
- We'll focus on: getting react-three-fiber set up in a Remix app; using
- nested routes and layouts to render a scene; moving scene state to the
- server with loaders and actions; streaming dynamic 3D resources to the
- client using resource routes; and finally, transitions and optimistic UI...
- in 3D! 💿 Rachel the Remix Disc will offer some nifty optimization tips
- along the way.
-
-
- It'll be a GL-and-web-fundamentals-fuelled blast!
- speakers:
- - Nick Small
-
-- title: "Web Vitals: The importance of measuring a user great web experience"
- time: 12:10 PM
- type: lightning
- description: >-
- Nowadays, building a working web application is much more than deploying it
- to production. The impact on the way your app is delivered to your end-users
- is also important.
-
-
- Making your app experience better translates into more engagement,
- conversions, and revenue. That's why it is also vital (pun intended) to know
- how your application behaves, and that's where Web Vitals help us get a
- clear overview of how our app is doing.
- speakers:
- - Erick Tamayo
-
-- title: "Making slow responses seem fast with stale-while-revalidate"
- time: 12:15 PM
- type: lightning
- description: >-
- The Cache-Control header has been around since HTTP/1.1 in 1997, yet for
- many of us, it's not something we think about every day. The
- stale-while-revalidate extension was proposed as early as 2010, but was only
- widely supported in modern browsers in 2019. In this talk, I will show you
- the power of stale-while-revalidate and how you can take advantage of it in
- your Remix project to make your slow responses seem really fast!
- speakers:
- - Scott Smerchek
-
-- title: "Building tech for social good with low-code tools"
- time: 2:25 PM
- type: lightning
- description: >-
- In this talk we are going to be talking about how to build hybrid apps that
- use a combination of frameworks like Remix and mixing them with no-code
- backends like Zapier and Airtable, so that they can be managed and modified
- by non-technical people.
-
-
- I will specifically go over how I replaced the admissions process at my
- children's preschool with a website and made them paperfree.
- speakers:
- - Vic Vijayakumar
-
-- title: "Expanding Remix with Rust"
- time: 2:30 PM
- type: lightning
- description: >-
- Remix's unique use of Loader and Action functions offers the unique
- opportunity to expand your data processing with Rust. Rust offers near
- native performance, memory safety through either the Node FFI or via
- compilation into WebAssembly. Learn the tricks to setup your Rust project to
- work with Remix, either on the server or the client, and take advantage of
- the most loved language with your favorite web framework!
- speakers:
- - Ben Wishovich
-
-- title: "Full Stack Fast: Data on the Edge"
- time: 2:35 PM
- type: lightning
- description: >-
- Why force your users to settle for either loading skeletons or slow page
- renders? Remix can bring your application rendering to the edge, but what
- about your data? Why should every request have to call back to a single
- database cluster in Virginia? For the best performance and experience for
- your users, store your data on the edge, alongside the rest of your
- application.
-
-
- We'll discuss how the original colocated server and database configuration
- worked, how it evolved with Jamstack, improved with next-gen data services,
- and how today's technology supports a new architecture altogether. But
- distributed systems are notoriously hard to design for, and edge-based
- storage is no different, with the challenges of synchronicity being a
- particularly difficult problem. I'll highlight the benefits of edge-based
- storage, how it compares to the other options, and I'll showcase a truly
- global Remix application built with Cloudflare's KV, Durable Objects and R2.
- speakers:
- - Greg Brimble
-
-- title: Remix your UI & UX to another level
- time: 2:45 PM
- type: regular
- description: >-
- Build performant web apps with a full-stack framework, Remix. Remix focuses
- on the UI to enjoy fast & resilient UX. Experience the "Remix magic" that
- enables no fetching & pre-fetch all in parallel before users make actions.
- As Remix focuses on UI & UX, why not share the "Remix magic" with the
- business users? In this talk, we're going to see together the combination of
- the new generation of a full-stack framework, Remix & a visual editor
- integrated headless CMS (Storyblok). Are you ready to explore a whole new
- level of experience?
- speakers:
- - Arisa Fukuzaki
-
-- title: "Magically create forms + actions with Remix Forms"
- time: 3:10 PM
- type: regular
- description: >-
- One of the beautiful things about Remix is how easy it is to enhance it to
- make our lives easier. In this talk, I'll show you how I built [Remix
- Forms](https://remix-forms.seasoned.cc/) and how I use it to:
-
- - Code only the parts of my forms that stray from our standard UI. The rest
- is magically rendered for me.
-
- - Never have to think again about client-side + server-side validations,
- pending indicators, and focus management (with focus on the first field with
- error even for server-side failures!)
-
- - Get form data, validate values, redirect or return errors with one helper.
- I focus on the mutation, not on the wiring.
-
- - Catch any typo or mistake right away with bulletproof typing, even for
- custom inputs.
-
- - Enjoy the autocomplete magic that comes along with it :)
- speakers:
- - Daniel Weinmann
-
-- title: "Incremental Remix"
- time: 3:35 PM
- type: regular
- description: >-
- Remix is fantastic for building brand-new apps. But the truth is most of us
- are slogging away on crusty old ones. How can we incorporate Remix into our
- stacks without rewriting everything? And how can we effectively sell our
- teams on the benefits of adoption? In this talk we'll explore some
- strategies that will let you gradually adopt Remix, progressively enhancing
- your tech stack.
- speakers:
- - Jon Jensen
-
-- title: "Outstanding Search Experiences with Remix and Algolia"
- time: 4:25 PM
- type: regular
- description: >-
- Outstanding search starts with two principles: immediate feedback and
- relevant results.
-
- Search-as-you-type experiences have become the standard since Google
- introduced Google Suggest and Google Instant on their search page in the
- 2000s. Users not only love the immediate feedback of instant experiences,
- they expect it. They also expect search to be excellent at understanding
- their intent, even when they misspell or forget words.
-
- Services like Algolia are designed to deliver instant, as-you-type, relevant
- results right from the first keystrokes. But what happens when the user's
- network is slow? What's relevant when the user didn't express intent yet? In
- this talk, we'll see how you can combine Algolia's client-side search with
- the power of Remix's server runtime to create snappy and delightful yet
- reliable and resilient search experiences that serve everyone.
- speakers:
- - Sarah Dayan
-
-- title: "Switching to Remix at Neighbor"
- time: 4:50 PM
- type: regular
- description: >-
- Neighbor is a marketplace that allows you to make extra cash by storing your
- neighbors' things in your extra space. After several years of using a
- standard React frontend generated by create-react-app, we've decided to move
- to Remix. I will discuss some of the crazy things we've done at Neighbor to
- work around the limitations of a standard CRA-generated application, why we
- chose to use Remix over other alternatives, and discuss some of the gotchas
- and learning that came out of the migration. If you work at a medium to
- large business and are interested in moving to Remix, this talk is
- especially for you. I will mostly stick to big picture concepts rather than
- diving deep into the code.
- speakers:
- - Dennis Beatty
-
-- title: Remix & high performance eCommerce
- type: backup
- description: >-
- Performances are key. That statement is true for any web application but
- even more for eCommerce applications that convert performances into revenue.
-
- Why are eCommerce projects more complex than others? What are the key topics
- and the special things that you need to take into account when building an
- eCommerce application in 2022.
-
- In this talk we will deep dive into all the things that must be dynamic and
- how to achieve performances.
-
- All explained with a Remix project example.
- speakers:
- - Sébastien Morel
-
-- title: "How To WebPageTest"
- time: 9:35 AM
- type: regular
- description: >-
- You cannot improve what you do not measure, and measuring page performance
- is at the heart of providing marvellous user experiences. "How To
- WebPageTest" is a talk where I will demonstrate how modern profiling using
- WebPageTest will provide the best insights. I'll show you tips and tricks on
- how to interpret the results, and I'll also expose you to key features that
- are best in class in performance testing.
- speakers:
- - Henri Helvetica
-
-- title: "Remixing a Symfony"
- type: backup
- description: >-
- In late 2020, I ran a Lighthouse test on a simple content page on Harvie,
- our farm management platform and Symfony app, and received a performance
- score of 31/100. The JavaScript bundle, the API requests, the database
- lookups, even with minimal UI to render, had a baseline score in the
- thirties! Along with customer feedback, this helped to catalyze a renewed
- commitment to performance at Harvie. Through numerous discussions, we walked
- through each step of page load, from networking to rendering, and identified
- where we could improve. After a year of rewrites and upgrades, our remaining
- detriment to overall performance was our frontend. We had been converting
- our Symfony twig templates into React SPA components and fell into the
- common problem of creating "request waterfalls", while our user had to stare
- at a loading screen. We needed a change, and for us, that was Remix. In this
- talk, I'll walk you through our team's journey with performance and how
- Remix has become a natural progression of that.
- speakers:
- - Emily Kauffman
-
-- title: "Intro To Remix - Working with Nested Routes and Parameterized Routes"
- type: backup
- description: >-
- We will walk through a simple demonstration of a remix application using
- nested routes and parameterized routes. The use of nested routes helps me
- with component design and separation when architecting an application.
- Parameterized routes / Dynamic Routes contain state information that can
- through the parameters that are defined on the route. This provides powerful
- flexibility when designing your app and app's components. Putting the two
- together in an simple solution to be a reference when you build something
- amazing.
- speakers:
- - Aaron K Saunders