Today, I decide to tackle language switching and dark mode on the site. I use Cursor, an AI-first code editor, exploring its various modes and learning more about its capabilities with Claude 3.5, the underlying model.
Cursorās setup is quite seemless as it is built on top of VSCode and all VSCode extensions can be carried across. Itās effectively a refined AI driven workspace within VS code rather than an entirely new editor. It provides three main tools: inline editing, a chat window, and a tool called composer that can automatically generate edits across multiple files. A few niceties is that it has tab-complete for next task, and that the chat window can talk to the whole codebase, not just the currently open file, so thereās some definite features that could be useful.
Language Switcher
My first task is to add a language switcher and Iād identified a visually appealing one from Umamiās cloud dashboard. Wonderfully, it is open-source and written in React. As a habitual React developer, this normally means plug and play. However, due to limitations in Astroās āislandā architecture, integrating React components off the shelf proves it can be cumbersome and it feels like there is lock-in once you start using Astro components. You can pass props from Astro to React components, but you canāt directly import and render Astro components in React components, so you kind of have to maintain two component collections, which sucks for obviously shareable things like icons.
Editors note: it is possible to pass Astro components as children to React components using a special slot prop with a kebab-case string value that becomes a camelCased prop inside the React component. Unclear if this would have helped in this case.
In the end I opt to write the switcher from scratch in Astro leveraging just the element structure and styles from Umamiās source code. This was more rewarding than you might expect: Astro components donāt have useEffectās, they store state in the DOM, and utilise vanilla js - so for simple use cases like this language switcher they are, simply put, infinitely better. After the frustration of trying to get the React implementation to work, this was a far more satisfying outcome on a few accounts.
The process made me think that when you lack subject-matter-expertise (e.g. React + Astro interoperability), it can start to feel like working with the AI is like throwing shit at a wall and hoping it sticks. In fairness the same is true with traditional coding too. The approach needs to be right. Cursor redeemed itself for not being a God-LLM anticipating my every wish and desire by effectively completing mundane tasks such as filling in the country flag icons for each country on the switcher for me, so Iāll give it a pass nonetheless.
Dark Mode
Dark mode initially seemed like it would be straightforward to implement, and Cursor handles the toggler button creation with ease. This involves writing a function to add the dark
class to the body
element and using localstorage to remember the userās choice. Then, to add the dark mode styles with tailwind it requires adding an extra dark:
prefixed class wherever there are relevant light mode ones. Cursorās āComposerā mode, which can auto-edit files, seemed promising but was actually quite hesitant to make broad changes across the codebase, even with a fairly straightforward task conceptually. I resorted to using the inline editor to go file by file, prompting to add dark mode styles. This was fast and effective, given what it was.
Some little Cursor frustrations were starting to add up. Itās quite weird how undo and redo also include the prompt editing history in the middle of the code editing history. I can see how that makes sense from one perspective, but itās a hassle when youāre trying to undo to a change before a given prompting operation. Composer is also somewhat experimental and the auto-application of edits crashed at some point, so it just started acting like a normal chat helper. On suspicion I restarted and this sorted it out. Stability is an issue.
I try to get Composer to do simple smart things like ask it to refactor both the language switcher and dark mode switcher to share a common site header button wrapper. Composer managed to extract the component, but only apply it to one place. Cool, but not cool.
Conclusion
All in all, the session highlighted the learning curve using Cursor both in terms of it being a slightly different editor and from a utilising AI prompt-driven development perspective. Prompt driven development felt clunky at moments. If Iād approached it from a traditional coding mindset instead of a playing dumb prompting mindset it might have been better some occasions. However, using prompting clearly excelled in specific tasks, like filling out country flags for the language switcher, creating the dark mode toggle, converting css to tailwind classes, and adding dark mode classes for dark mode. Working across multiple files to edit them is still just very clunky as it stands.

