Here’s a handy little tool for generating CSS with :has()
selectors in order to do quantity queries.
What the fuck happened to making HTTP requests? You used to just type curl <a href="http://example.com" rel="nofollow">example.com</a>
and boom, you got your goddamn response. Now everyone's downloading 500MB Electron monstrosities that take 3 minutes to boot up just to send a fucking GET request.
You know what's better than downloading Postman? Not downloading Postman. cURL is already installed on your machine. It's been there since forever. It works. It's fast. It doesn't need to render a fucking Chromium instance to make a web request. It doesn't depend on a service to run. It doesn't require an "Enterprise" subscription for basic features.
Oh, you need to:
curl -X POST
curl -H "Header: value"
curl -F <a href="mailto:file=@file.txt">file=@file.txt</a>
curl -c cookies.txt -b cookies.txt
curl -L
curl -u user:pass
Meanwhile Postman is over here asking you to create an account to sync your "collections" to the cloud. It's a fucking HTTP request, not your photo library.
You know what has great UX? The command line you're already using. No clicking through 47 tabs. No "Workspaces." No "Environments" dropdown menu. Just type the fucking command. Your history is in your shell. Your "collections" are called shell scripts. Your "environments" are called environment variables, and they've existed since 1979.
Want to save a request? Put it in a file. Want to share it with your team? It's text. Copy it. Paste it. Done. No JSON export/import bullshit. No proprietary formats.
cURL executes in milliseconds. You know how long it takes Postman to start? Long enough to question your career choices. And don't even get me started on these new "modern" alternatives like Insomnia and HTTPie Desktop. Congratulations, you've turned a 2MB command-line tool into a 300MB desktop app. Progress!
Shut up. You can pipe cURL to jq
:
curl -X POST <a href="https://api.example.com/graphql" rel="nofollow">https://api.example.com/graphql</a> \
-H "Content-Type: application/json" \
-d '{"query": "{ users { name } }"}' \
| jq '.'
Now you have syntax highlighting and JSON parsing. Total install size: ~10MB. Total startup time: instant. Total RAM usage: negligible. Total feelings of superiority: immeasurable.
Don't trust yourself with JSON syntax? Fine, use jo
:
curl -X POST <a href="https://api.example.com/api/users" rel="nofollow">https://api.example.com/api/users</a> \
-H "Content-Type: application/json" \
-d "$(jo 'user[name]=John' 'user[email]=john@example.com')"
Beautiful. Fast. No Electron or React in sight.
Q: But I can't see my request history!
A: Yes you can, it's called history | grep curl
. Or write your commands in a fucking file like an adult.
Q: How do I organize my requests?
A: Put your shell scripts into directories, genius.
Q: The syntax is hard to remember!
A: Type man curl
or curl --help
. Or literally just Google it once and save the command. You can remember 400 Kubernetes commands but not curl -X POST
?
Q: What about team collaboration?
A: It's a text file. Put it in Git. You know, that thing you should be using anyway? Now your requests have version control, code review, and diffs. For free. Revolutionary, I know.
Q: But Postman has testing and automation!
A: So does cURL in a shell script with ||
and &&
and actual programming languages. You want assertions? Pipe to grep
or write a 3-line Python script. Done.
Q: What about cookie management?
A: -c
to save cookies, -b
to send them. This has been solved since 1999. Read the manual.
It's been downloaded over 20 billion times. It supports 25+ protocols. It's in cars, refrigerators, TV sets, routers, printers, phones, and every goddamn server on the planet. It's maintained by people who actually understand networking, not some VC-funded startup that'll slap "AI" on it next quarter.
Stop using resource-hogging garbage. Stop creating accounts for basic functionality. Stop pretending you need a GUI to make HTTP requests.
Just use cURL.
When we think about state management in front-end frameworks, we often focus on the API—hooks, observables, or signals. However, there's a deeper paradigm shift at play: where rendering happens. Traditional state management like React hooks triggers renders at the point where state is created, while signal-based approaches like Preact Signals or Solid.js trigger renders only where state is consumed.
This shift from "render where you create state" to "render where you use state" has profound implications for performance, code organization, and mental models.
In traditional state management with React hooks, when you call useState
, any update to that state causes the component—and
all its descendants—to re-render. It doesn't matter whether those descendants actually use the state; they're caught in the
render wave simply because they're children of the component that holds the state.
const Parent = () => {
const [count, setCount] = useState(0);
return (
<>
{/* re-renders even though it doesn't use count */}
<ChildA />
<ChildB />
{/* re-renders, actually uses count */}
<ChildC count={count} />
</>
);
};
With signal-based rendering, the paradigm inverts. A signal is a reactive primitive that tracks its own dependencies. When you create a signal, it doesn't trigger re-renders at the creation site. Instead, rendering only occurs at components that actually access the signal's value.
const Parent = () => {
const count = useSignal(0);
return (
<>
{/* do NOT re-render */}
<ChildA />
<ChildB />
{/* only re-renders if it reads count.value */}
<ChildC count={count} />
</>
);
};
This granular reactivity means only the precise components that depend on the signal will re-render when it updates. The mental model shifts from "prevent unnecessary re-renders" to "re-renders only happen where they're needed."
This difference becomes even more pronounced when dealing with the Context API. In React, when you distribute state through context and update it, all consumers of that context re-render, regardless of whether they actually read the updated value.
const CountContext = createContext();
const Provider = ({ children }) => {
const [count, setCount] = useState(0);
const [name, setName] = useState('');
return (
<CountContext.Provider
value={{ count, name, setCount, setName }}
>
{children}
</CountContext.Provider>
);
};
const ComponentA = () => {
const { name } = useContext(CountContext);
// Re-renders when count changes,
// even though it only uses name.
return <div>{name}</div>;
};
With signals in context, the reactivity is surgical. The context can hold signals, and only components
that actually call .value
on a signal will subscribe to its updates.
const CountContext = createContext();
const Provider = ({ children }) => {
const count = useSignal(0);
const name = useSignal('');
return (
<CountContext.Provider value={{ count, name }}>
{children}
</CountContext.Provider>
);
};
const ComponentA = () => {
const { name } = useContext(CountContext);
// Only re-renders when name changes,
// not when count changes
return <div>{name.value}</div>;
};
This is a game-changer for large applications where context is used to distribute state across many components. You no longer need to split contexts to prevent unnecessary re-renders or reach for complex optimization patterns.
Let's visualize how re-renders propagate through a component tree:
In state-based rendering, when state updates, the entire subtree from the point of state creation re-renders.
You need to manually optimize with React.memo
, shouldComponentUpdate
, useMemo
, and useCallback
to
prevent unnecessary work.
All descendants re-render (shown in red), regardless of whether they actually use the state.
Only GC 2
genuinely needs the update, but Child 1
, Child 2
, Child 3
, GC 1
, and GC 3
all re-render unnecessarily.
In signal-based rendering, only components that actually read the signal's value re-render. The component hierarchy is irrelevant—what matters is data dependency, not component ancestry.
Only GC 2
, which actually accesses signal.value
, re-renders (shown in green).
All other components remain unchanged (shown in gray), even though they're part of the same component tree.
Preact has a few utilities to take this further with control flow components like Show
and For
.
These components scope reactivity even more precisely.
const items = signal([]);
// When the items signal updates, only the affected items re-render
<For each={items}>
{(item) => (
<div>
{/* Only this item re-renders when item.value changes */}
<span>{item.name.value}</span>
<button
onClick={() => item.count.value++}
>
{item.count.value}
</button>
</div>
)}
</For>
Compare this to classic hooks, where changing an item in a list might trigger re-renders across sibling items, the parent component, and any other children—unless you've carefully memoized everything.
These control-flow components scope the re-render of a Signal (be that a derived computed or plain signal value) down to its JSX children.
This paradigm shift has tangible performance implications:
React.memo
, shouldComponentUpdate
, useMemo
, or useCallback
.
The framework's reactivity system handles optimization automatically.It's worth noting that state-based rendering isn't inherently bad. For small components or applications where re-renders are cheap, the hooks model is simple and sufficient. The cost of re-rendering a few dozen components is often negligible.
The trade-off becomes significant in:
The shift from state-based to signal-based rendering is more than a performance optimization—it's a paradigm shift in how we think about reactivity. Instead of preventing re-renders through memoization, we only trigger re-renders where they're needed.
This inversion—from "render where you create state" to "render where you use state"—aligns our code with the actual data flow. It makes applications faster by default and simplifies the mental model: if you read a signal, you'll update when it changes. If you don't, you won't.
As frameworks like Preact Signals and Solid.js demonstrate, this isn't a theoretical improvement—it's a practical one that makes building performant, maintainable applications easier. The future of front-end reactivity is fine-grained, and it's already here.