Alex Vipond

Alex Vipond

@alexvipond.dev

I'm into web development and social impact. Working on BetterHelp and Baleada 🇺🇸🇭🇳 https://alexvipond.dev https://baleada.dev

57 followers106 following82 posts

Editing code is still a joy, Zed's Emmet wrap-with-abbreviation command supports multi-cursor editing as you type the abbreviation 😍

Is anyone running the Linux version of @zed.dev on an android device yet? I'm curious about the workflow of using phone + portable keyboard + Zed multiplayer + agent panel so I can run prompts remotely, with no need for SSH, and retaining the ability to review agent edits in a multibuffer 🔥🥵🔥

If you want zero-cost, the best solution right now is Zed + BYOK connecting to Mistral zed.dev/docs/ai/llm-... Their devstral models are free, and IME perform well on small-to-medium, relatively well-defined/straightforward/common/known tasks.

zed.devLLM Providers | Zed Code Editor DocumentationLearn how to use and customize Zed, the fast, collaborative code editor. Official docs on features, configuration, AI tools, and workflows.
Alex Vipond @alexvipond.dev

Been a while since I used @zed.dev, and HOLY SHIT it got good Multiple cursors editing multiple files, and Claude Code deeply integrated. I've never been able to refactor this fast. I'm working on my editor settings while the agent runs—here's what I have so far gist.github.com/AlexVipond/a...

For the best code quality, especially on large changes, innovative changes, or tasks where you're not sure of a solution but think the LLM might crack it open for you, you're still gonna want Zed's paid plan + Claude.

Your app is a graph. Objects are nodes, and their relationships determine graph structure. User -> TaskList[] TaskList -> Task[] User -> User[] (friends) etc. User actions change the graph by adding nodes and defining relationships.

View full thread

The frontend code is all type-safe, too. For example, the return type of this snippet is automatically inferred as an array of game objects: // Get a list of the user's active games relatedResources.get({ from: { kind: 'user', id: 'ABC' }, kind: 'is-playing', to: { kind: 'game' }, })

Your app is a graph. Objects are nodes, and their relationships determine graph structure. User -> TaskList[] TaskList -> Task[] User -> User[] (friends) etc. User actions change the graph by adding nodes and defining relationships.

View full thread

Across every API and every page load, the payload going over the network is always the same data structure, just with different data, describing different subgraphs in the app. You never have to design custom API payloads, write custom schemas, or sync custom TS types.

This is the data structure I'm using on a project right now. It supports an arbitrary number of different relationships between any two resources in the app, and returns info about where and when the relationship was established.

Your app is a graph. Objects are nodes, and their relationships determine graph structure. User -> TaskList[] TaskList -> Task[] User -> User[] (friends) etc. User actions change the graph by adding nodes and defining relationships.

When you load a page, request a subgraph, based on what the user needs and is authorized to see. On the frontend, write utility functions so you can walk/parse/read/render the graph more ergonomically.

When a user takes an action, update the graph adding new nodes and/or relationships based on the action. Re-render optimistically. Locally, store events that describe the changes. Depending on your needs, store graph snapshots. Send the updated graph to your API to sync the backend.

Alex Vipond reposted

People give `useEffect` a bad rap, but it isn't usually the source of the problem. The real problem is too many `useState`s. Devs fail to see how their data is connected and model it too discretely. As those connections appear, it is easier to synchronize than refactor the model. 1/

If you play guitar The solution is Ampero II & Ampero Switch Play in Stomp mode, using stomps to change scenes (press a single stomp to turn multiple effects on/off, and/or change parameters, with natural delay & reverb spillover, and no audio gaps 🤯) Use the Ampero Switch to cycle patches 🤘

Single-table design is magic This is the Eloquent query I run to get - lat/lng of the given location - Profiles of current user & their friends - Profiles of birds they identified in that location, including timestamps - Profiles of their multiplayer birding sessions in that location

I have no clue if this is going to be fast or memory-efficient at scale, but the querying feels great, and I've completely avoided the complexity of Eloquent relationships and helper tables. Gonna make it work before I make it fast

I just wrote the Inertia controller for an app dashboard view that reads 5 types of resources and 16 relationships from the DB. It uses 1 query, and it does not need to eager-load any model relationships, so I can use the query's cursor() method and iterate over the results with low memory usage.

This works because the entire app is written with a DynamoDB-inspired single-table design. Resources' profile data is denormalized—I duplicate it and store in a JSON column as needed to support access patterns. DB writes are complex, but my reads seem cheap and extremely easy so far.

I think Laravel + single-table design might be groundbreaking stuff, but let me know if you've seen any projects do this! I'm currently running it with Inertia and SQLite, but in theory you could easily swap those out

Alex Vipond reposted

Something that sounds easy, but is tricky to get right: wrap text around the Dismiss button of a clickable card. The tricky part is making sure you don't sacrifice accessibility features like grouping, labeling, focus rings, etc. Here's how I do it: alexvipond.dev/blog/wrap-te...

alexvipond.devAlex Vipond — web development, social impactI'm into web development and social impact. I write code and create content for these topics, and I share it on my website.

This VS Code config will add @tailwindcss.com Intellisense to all code between a starting comment /** tw */ and an ending comment /** endtw */ This is incredibly useful for reusable classes tucked away in a JS variable or helper function, which TW Intellisense won't automatically check

Copy-pasteable: "tailwindCSS.experimental.classRegex": [ [ "\\/\\*\\* tw \\*\\/([\\s\\S]*?)\\/\\*\\* endtw \\*\\/", "(?:'|\"|`)([^\"'`]*)(?:'|\"|`)" ], ]

Vite apps can shave off some bundle size by setting `build.rollupOptions.treeshake` to `smallest`. This allows rollup to treeshake more aggressively—for example, it will now shake unused third-party libraries that didn't set `sideEffects: false` in their package.json.

Here's my progressively enhanced design & positioning logic for popups, implemented with CSS, Tailwind, ResizeObserver, and Vue. Zero usage of `getBoundingClientRect`, scroll listeners, or any other techniques that thrash the layout or block rendering!

View full thread

4. Else, anchor the popup to the controller. Set max height to 50dvh minus half the height of the popup controller. Try anchoring to the bottom first, then top, then right, then left. (In all cases I've tested, either the top or bottom works, and the right & left fallbacks are just there for safety)

I implemented all this in a component I call `PortaledPositioned`, which is reusable for all popups (selects, menus, modals, tooltips, etc.) in the design system I'm building. Haven't decided how to release this code yet, but it'll be available eventually. Hit me up if you want an early look!

Here's my progressively enhanced design & positioning logic for popups, implemented with CSS, Tailwind, ResizeObserver, and Vue. Zero usage of `getBoundingClientRect`, scroll listeners, or any other techniques that thrash the layout or block rendering!

1. Portal the popup to the end of the `body`. 2. If screen size indicates mobile device, use a drawer design. Bottom drawer for portrait, side drawer for landscape. 3. Else if the browser doesn't support CSS anchor positioning, center the popup on the screen, on top of a semi-transparent underlay.

`select` typeahead UX was something I wanted to improve on when I first started writing Baleada Vue Features composables like `useSelect`. I'm finally building a real design system on top of these composables, and loving how flexible, powerful, and observable they are.

The typeahead query and the time elapsed/remaining until the typeahead auto-clears are both reactive, so my custom component can render the query and a little time animation. When you initially call `useSelect`, you can configure fuzzy-matching thresholds, and the millisecond delay until auto-clear.

Alex Vipond reposted

🎁 A surprise holidays gift: after over a year of hard work, we have just published Rolldown 1.0.0-beta.1!

Alex Vipond reposted

The Epic Programming Principles: the guide I use to make decisions as a software engineer. Transcending specific tools or frameworks, these principles will help you guide your career, craft, and technical choices. See details and examples for each principle here: www.epicweb.dev/principles 📖