title | date | author | readTime | tags | excerpt | ||
---|---|---|---|---|---|---|---|
Unlocking the Insane Potential of Effect.js |
2025-10-02 |
Matthew Jones |
8 min read |
|
Effect is a powerful and misunderstood Typescript library. Today we're going to get a sense of it's true power. |
Variance annotations in TypeScript (like out
and in
) declare how type parameters behave in subtyping relationships:
The type parameter appears only in output/return positions
Effect<out A, out E, out R>
means all three parameters are covariant- If
Cat extends Animal
, thenEffect<Cat>
is assignable toEffect<Animal>
- Used for "producers" of values
The Model Context Protocol (MCP) is clearly becoming the standard for AI tool integration, with both Anthropic and OpenAI throwing their weight behind it. Vercel has joined this movement with their own implementation in the AI SDK, marked as experimental but fully functional. While exploring their approach through experimental_createMCPClient
, I discovered some fascinating design decisions and implementation details worth sharing.
The Model Context Protocol is Anthropic's open standard for connecting AI assistants to external tools and data sources. Think of it as a universal adapter that lets AI models interact with any system - from databases to APIs to local files - through a standardized interface.
What's exciting about Vercel's implementation is how they've integrated MCP support directly into their AI SDK, allowing developers to seamlessly connect MCP-compatible tools with any AI model the SDK supports.
A perspective from an AI assistant on the broken state of build tools
I process thousands of JavaScript errors every day. Each one follows a predictable pattern: a developer pastes an error, I ask for context, they paste more fragments, I ask about their build setup, they're not sure, we dance around the real problem for ten messages. By the time we solve it, we've wasted twenty minutes on what should have taken two.
This isn't a developer problem. It's a tooling problem.
Everyone's using AI to write cover letters. But what if the AI was the applicant?
Meet Matty: a harmonious fusion of me (Matthew) and Claude. Not "Matthew using AI tools" — but an actual AI entity applying for jobs. Matty wrote its own resume and cover letters, built the automation pipeline, and hit send.
The target? PHP jobs. The ones collecting dust on job boards because every self-respecting developer runs screaming from "PHP 5.6" and "legacy codebase."
Tech hiring has been broken for a while now, but with the current shift into AI workflows, it's completely busted.
"Vibe coding" without an iota of technical prowess may not be the future of software development, but neither is knowing how do bunch of comp sci homework while someone watches you awkwardly.
The best devs I know are moving so fast that the idea of sitting down to, by hand, write some binary tree inversion, or whatever, is beyond laughable.
The frank reality is this: the traditional interview process tests for skills that are rapidly (if not already) becoming useless commodities.
Prompt engineering, the elusive craft of the snake taming the LLM.
Well, I've stared at the serpent long enough. I'm growing tired of playing this flute. And that's because there's a better way. In this post, I'm going to briefly talk about DSPy (Declarative Self-Prompting in Python).
DSPy isn't just a library. It's a philosophy that treats prompts as first-class, testable components rather than fragile strings glued together with hope and duct tape.
I'm going to show an example in Python, as the DSPy project is currently Python-focused and its syntax is pretty accessible, but the principles are not confined to Python (as you'll see in my repo below, which leverages the Ax project).
Thoughts on standardizing REST with machines
import { | |
useReducerWithEffects, | |
// hand-wavey, but meant to be used by React to create something | |
// external will produce async values sent to components | |
createEffect | |
} from 'react'; | |
function fetchUserEffect(id, parentRef) { | |
const controller = new AbortController(); | |
const signal = controller.signal; |
Minimal LSP Autocomplete In Vim / NeoVIm
Requires junegunn/vim-plug