Skip to content

Instantly share code, notes, and snippets.

View AndrewIngram's full-sized avatar
🦊
Being foxy

Andy Ingram AndrewIngram

🦊
Being foxy
View GitHub Profile
@AndrewIngram
AndrewIngram / _Drizzle Migration with Vercel Postgres.md
Last active April 21, 2024 16:45
Drizzle Migration with Vercel Postgres

Generate migrations with:

pnpm drizzle-kit generate:pg

Run with:

pnpm tsx ./migrate.ts
@AndrewIngram
AndrewIngram / CurrentTime.tsx
Created November 21, 2023 00:04
Current time in React without hydration errors
import { Suspense } from "react";
import CurrentTimeClient from "./CurrentTimeClient";
export default function CurrentTime() {
const locale = "en-GB";
const dateConfig = {
hour: "numeric",
minute: "numeric",
second: "numeric",
"use client";
import { cache, unstable_postpone } from "react";
import { preload } from "react-dom";
const loadImage = cache((src: string) => {
return new Promise<void>((resolve, reject) => {
const img = new Image();
img.src = src;
import { useRef, useCallback, useInsertionEffect } from "react";
// Approximation of React's upcoming useEffectEvent hook
// This gives us a non-reactive effect event callback, it will always use the latest version of
// the callback, rather than the one that was closed over.
export default function useEffectEventShim<T extends (...args: any[]) => any>(
fn: T
): (...funcArgs: Parameters<T>) => ReturnType<T> {
const ref = useRef(fn);
@AndrewIngram
AndrewIngram / 01_Readme.md
Last active March 6, 2023 02:06
Sketch of migrating eager to lazy popovers with RSC + Server Actions

A simple sketch of how we migrate a "card" component to lazy-load its popover content by server actions. The after (lazy) version is visibly more complex, but the steps involved are fairly straightforward -- and if it were a common pattern, there are steps that could be taken to abstract it into something simpler.

Important to note that if it's determined that server actions can only be defined in server components, the solution would be a little different.

@AndrewIngram
AndrewIngram / R2_storage.ts
Last active March 20, 2024 11:05
Read/write from Cloudflare R2 in a Vercel edge function w/default
import { AwsClient } from "aws4fetch";
import { deflate } from "pako";
const R2_ACCOUNT_ID = "SOMETHING"
const R2_ACCESS_KEY_ID = "SOMETHING"
const R2_SECRET_ACCESS_KEY ="SOMETHING"
const R2_BUCKET = "SOMETHING"
const R2_URL = `https://${R2_BUCKET}.${R2_ACCOUNT_ID}.r2.cloudflarestorage.com`;
@AndrewIngram
AndrewIngram / route.ts
Last active February 17, 2023 02:14
Next.js SItemap route with streaming (requires Node 18+)
import { SitemapStream, EnumChangefreq } from "sitemap";
import { getAllPosts } from "~/data";
import { Readable } from "node:stream";
async function* getSitemapUrls(request: Request) {
const url = new URL(request.url);
const origin = `${url.protocol}//${url.host}`;
@AndrewIngram
AndrewIngram / route.ts
Last active February 16, 2023 22:45
Next.js Sitemap route handler
import { SitemapStream, EnumChangefreq, streamToPromise } from "sitemap";
import { getAllPosts } from "~/data";
import { Readable } from "stream";
async function* getSitemapUrls(request: Request) {
const url = new URL(request.url);
const origin = `${url.protocol}//${url.host}`;
@AndrewIngram
AndrewIngram / Await.tsx
Created February 7, 2023 18:08
Remix-inspired "Await" component for RSC / Next 13
import { use } from "react";
type Props<T> = {
resolve: Promise<T>;
children: (value: T) => React.ReactElement;
};
export default function Await<T>({ resolve, children }: Props<T>) {
const value = use(resolve);
@AndrewIngram
AndrewIngram / 01_readme.md
Last active January 20, 2023 21:49
MASSIVE HACK ALERT: Using headers() and cache() in Next 13.1 API routes

Warning, this is a bad idea. It'll eventually break and use undocumented framework internals

Using headers() and cache() in Next 13.1 API routes

Note: API routes are still only supported in the pages folder, not app.

I was playing around with using API routes with the experimental app dir stuff in Next 13, and I was frustrated at having to use completely different code paths for accessing the request headers and cookies compared to in server components. So I hacked together a workaround which you definitely shouldn't use.

Usage requires two steps, one is easy, the other is invasive: