Sign in

James A Rosen

@jamesarosen.com
518 followers 655 following 629 posts

Dad to 👧👧🐈🐈‍⬛🐈‍⬛. Software engineer looking for the next career move. Napa, CA Bicycle & Pedestrian Commissioner. Francophone (+/-).

PostsRepliesMedia
James A Rosen @jamesarosen.com · 10/08/2025
This is my deactivated (but not deleted) Facebook account, last updated in 2018 Whatever the police found isn't my account
110
James A Rosen @jamesarosen.com · 15/06/2025
My #NoKings protest sign Chicken TACO
A protest sign depicting Trump as a cartoon chicken wrapped in a soft taco shell
050
James A Rosen @jamesarosen.com · 23/04/2025
My father gave me a cool bird feeder with a webcam for my birthday. We had our first visitor today! A California Towhee, I’m pretty sure
A close-up of a brown and rust bird eating seed. Behind the bird is a green garden, brown house, and a clear blue sky.A close-up of a brown and rust bird pondering the seed it just ate. Behind the bird is a green garden, brown house, and a clear blue sky.
050
James A Rosen @jamesarosen.com · 06/04/2025
So many happy bees on the borage in our garden today 😀🐝❤️
A bee landing on a purple borage flowerA bee buzzing around a borage flowerA bee collecting pollen from a borage flowerA bee on the underside of a borage flower
020
James A Rosen @jamesarosen.com · 05/04/2025
“Melt ICE, not icebergs” #indivisible #habdsoff
Hundreds of people protest Trump and Musk in downtown Napa, CA
141
James A Rosen @jamesarosen.com · 21/02/2025
I tweaked it to lower the delay and return a random number. Five invocations at stale result in 10 network waterfall entries. Five are "fetch" and "disk cache". The sixth is text/plain, 291B. The remainder are text/plain, 0B. All the "fetch" responses have the same random number.
Chrome dev tools network pane showing 10 network request/responses. All 10 are 200 responses. The first five have type=fetch, size=(disk cache). The last five all have type=text/plain. The 6th has size=291B. 7-10 have size=0B.
120
James A Rosen @jamesarosen.com · 21/02/2025
The five responses all come back together. One of them has bytes. The other four are empty because Chrome used one to fulfill the others.
Chrome dev tools network panel. Five responses, all 200. One of them has 318B response; the others all have 0.
130
James A Rosen @jamesarosen.com · 20/02/2025
Both ComponentType and FC are generic on Props, with default `{}` (empty object). You need to specify a props type, but the only type that will for for all possible entries in MAP is `ComponentType<any>`. That works and allows TS to discriminate the union via `[variant]`. Great suggestion!
VSCode screenshot with the following React-TypeScript code:
```
const Foo: FC<{ foo: string }> = ({ foo }) => <div>{foo}</div>;
const Bar: FC<{ bar: number }> = ({ bar }) => <div>{bar}</div>;
const Baz: FC<{ baz: Date }> = ({ baz }) => <div>{baz.toISOString()}</div>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const SubComponents: Record<string, ComponentType<any>> = {
  foo: Foo,
  bar: Bar,
  baz: Baz,
} as const;

type WrapperProps = {
  [K in keyof typeof SubComponents]: { variant: K } & ComponentPropsWithoutRef<typeof SubComponents[K]>;
}[keyof typeof SubComponents];

export const Wrapper: FC<WrapperProps> = ({ variant, ...props }) => {
  const SubComponent = SubComponents[variant];
  return <SubComponent {...props} />;
};
```
140
James A Rosen @jamesarosen.com · 20/02/2025
I like the MAP approach because it's very extensible. The ComponentPropsMap is redundant and can be computed. Code in alt text.
Screenshot of VSCode with the following React-TypeScript code:
```
const Foo: FC<{ foo: string }> = ({ foo }) => <div>{foo}</div>;
const Bar: FC<{ bar: number }> = ({ bar }) => <div>{bar}</div>;
const Baz: FC<{ baz: Date }> = ({ baz }) => <div>{baz.toISOString()}</div>;

const SubComponents = {
  foo: Foo,
  bar: Bar,
  baz: Baz,
} as const;

type WrapperProps = {
  [K in keyof typeof SubComponents]: { variant: K } & ComponentPropsWithoutRef<typeof SubComponents[K]>;
}[keyof typeof SubComponents];

export const Wrapper: FC<WrapperProps> = ({ variant, ...props }) => {
  const SubComponent = SubComponents[variant];
  // @ts-expect-error TS can't collapse the type of SubComponent, props
  return <SubComponent {...props} />;
};
```
010
James A Rosen @jamesarosen.com · 03/02/2025
I just did my seasonal maintenance:
Two end-grain cutting boards with a jar of bees-wax-mineral-oil. The boards are shiny, with a fresh coat, though well “loved” with scratches.
110
James A Rosen @jamesarosen.com · 02/02/2025
Mass protests are planned for February 5th. Every state capital at noon local. www.reddit.com/r/50501/ #uspol #50501
Poster with a man wearing a gas mask. Text reads
Impeachment gathering
Feb 5th at all State Capitals
Peaceful protest
Impeachment of 47th Prez
12pm your time
158
James A Rosen @jamesarosen.com · 22/01/2025
Seen in Napa: Abolish PG&E No argument from me. I hope the 21st Century sees a massive decentralization of power (literally and figuratively).
Chalk drawing on a sidewalk next to a park. It says “Abolish PG&E” in black, yellow, and bright blue alongside some Minions.
000
James A Rosen @jamesarosen.com · 07/12/2024
This is such a nice UI element. @aljazeera.com has an "In case you're just joining us" element at the top of (some) stories. As a reader, it so easy to decide whether to read that or skip it. The information is important context for the story. I'm going to use this pattern.
An Aljazeera article on a war in Syria. The article begins with a section headed "In case you're just joining us" and has 5 bullet-point sentences providing context for the following article.
010