# Hugo Richard
::hero{subtitle="Software Engineer & Designer at Vercel" title="Hugo Richard"}
Building with obsession β² Open source by default, [Nuxt](https://nuxt.com){rel=""nofollow""} at heart.
::
:contact-links
::experience
---
items:
- company: Vercel
url: https://vercel.com
role: Software Engineer & Designer
period: 2025 β β
- company: NuxtLabs
url: https://nuxtlabs.com
role: Software Engineer
period: 2025
- company: Freelance
role: Design & Development
period: 2019 β 2024
---
::
::projects{featured}
::
::writing-list{:limit='5'}
::
# 5 Amazing Raycast Snippets for Enhancing Your Nuxt (Vue) Projects
In the realm of web development, where efficiency is as valuable as expertise, tools that streamline and simplify our workflow are indispensable. Among these, Raycast snippets emerge as a powerful ally, especially for those working with Nuxt and Vue frameworks. But what exactly are these snippets, and how can they transform your development experience?
## What Are Raycast Snippets ?
Raycast snippets are small, reusable pieces of text or code that can be quickly inserted into your work. Think of them as shortcuts for frequently used content - whether it's code, canned email responses, or even emojis. They are designed to save time and reduce repetitive typing, allowing developers and writers to work more efficiently.
## How to Use Raycast Snippets
Using Raycast snippets is straightforward. Once you've created or imported a snippet within the Raycast app, you can assign a specific keyword to it. This keyword acts as a trigger - whenever you type it in any application, the snippet will automatically expand in place, replacing the keyword with the full text or code of the snippet.
For instance, if you have a snippet for a standard email sign-off, you can assign a keyword like `sig1`. Typing `sig1` in an email will then automatically expand to the full signature text. This feature is especially useful in coding, where you can have snippets for common code patterns or configurations.
## Component Template: `!comp`
The `!comp` snippet is a basic yet powerful template for creating new Vue components. It includes a script setup with TypeScript support, a template section, and scoped styling. This snippet is ideal for rapidly scaffolding new components in your project.
**Usage Example:** Use `!comp` to quickly create new Vue components, ensuring consistency and saving time on setup.
```vue [MyComponent.vue]
{{ item }}
```
## API Handler Template: `!api`
Handling API requests is a common task in modern web applications. The `!api` snippet provides a template for creating API handlers using `h3`, a lightweight HTTP toolkit. This snippet streamlines the process of setting up API routes and handling requests.
**Usage Example:** Implement the `!api` snippet for creating efficient API routes in your Nuxt application, especially when dealing with CRUD operations.
```ts
import { H3Event } from "h3";
export default defineEventHandler(async (event: H3Event) => {
const body = await readBody(event);
// your_api_logic
});
```
## State Management with Pinia: `!store`
State management is crucial in large-scale applications. The `!store` snippet utilizes Pinia, a Vue store, offering a structured template for managing application state. It includes a state definition, getters, and actions.
**Usage Example:** Utilize `!store` for setting up store modules in your Nuxt/Vue app, managing state more effectively and cleanly. the { clipboard } while be replaced by your actual clipboard.
```ts
import { defineStore } from 'pinia';
type {clipboard}Store = {
count: number;
}
export const use{clipboard}Store = defineStore('{clipboard}', {
state: (): {clipboard}Store => ({
count: 0,
}),
getters: {
getCount(): number {
return this.count;
}
},
actions: {
increment() {
this.count++;
},
}
});
```
## Composable Function Template: `!cps`
Composable functions in Vue 3 bring reusability and organization to your code. The `!cps` snippet offers a template for creating these functions, aiding in maintaining a clean and modular codebase.
**Usage Example:** Use `!cps` for creating reusable composable functions that can be shared across components, enhancing code reusability and maintainability.
```ts
export function use{clipboard}() {
const {clipboard} = ref(null);
// Composable logic
return { {clipboard} };
}
```
## Fetching Data with Composition API: `!fcomp`
The `!fcomp` snippet is designed for fetching data using Vue's Composition API. It provides a setup for making HTTP requests, handling loading states, and managing errors, all within a component.
**Usage Example:** Implement `!fcomp` in scenarios where you need to fetch data from an API, providing a robust structure for data fetching and state management.
```vue
Load Data
Loading...
{{ error }}
{{ data }}
```
## Why Use These Snippets?
### Enhance Productivity
Raycast snippets save time and effort by providing ready-to-use code templates, allowing you to focus on the unique aspects of your project.
### Maintain Consistency
Using standardized snippets ensures consistency across your codebase, making it easier to read, maintain, and collaborate on.
### Streamline Development
Snippets cater to common development tasks, streamlining your workflow and reducing the likelihood of errors or oversights.
### Foster Learning
For new developers or those new to Nuxt and Vue, these snippets offer insight into best practices and efficient coding patterns.
In conclusion, incorporating these Raycast snippets into your Nuxt and Vue development workflow can significantly enhance productivity, maintain code consistency, and streamline your development process. Whether you're building a small project or a large-scale application, these snippets are invaluable tools in the modern developer's arsenal.
# From Local to Production: Deploy the Latest Nuxt Stack with Docker
The modern Nuxt stack is evolving rapidly, bringing exciting new features and improvements. In this guide, we'll explore how to properly containerize and deploy a Nuxt application using the latest versions of Nuxt UI and Content. You'll learn how to set up Docker with best practices, automate builds with GitHub Actions, and deploy your application anywhere - whether it's Coolify, your own server, or any other platform.
As of January 2025, we're working with some cutting-edge versions:
- Nuxt UI v3.0.0-alpha.12 - A powerful component library revolutionizing UI development
- Nuxt Content v3.0.0- Content management reimagined
- Nuxt v3.15.1 - The rock-solid foundation
While these alpha versions are still evolving, they're stable enough for production use and offer significant improvements over their predecessors. Let's dive into containerizing this stack properly.
## Setting Up Your Project
Before we start with Docker, ensure your Nuxt project is properly configured. Here's a minimal `package.json`:
```json [package.json]
{
"name": "nuxt-app",
"private": true,
"dependencies": {
"@nuxt/content": "^3.0.0",
"@nuxt/ui": "^3.0.0-alpha.12",
"@nuxt/image": "^1.9.0",
"nuxt": "^3.15.1"
}
}
```
## The Dockerfile Explained
Our `Dockerfile` uses a multi-stage build process to create an optimized production image. Let's break down each section:
```dockerfile [Dockerfile]
FROM node:22.13.0-alpine AS build
WORKDIR /app
COPY pnpm-lock.yaml package.json ./
# Enable corepack for pnpm support
RUN corepack enable
RUN pnpm install --frozen-lockfile --prod
COPY . .
RUN pnpm run build
FROM node:22.13.0-alpine AS final
WORKDIR /app
COPY --from=build /app/.output .output
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]
```
π‘ Pro Tips:
- Using `alpine` reduces the base image size by \~300MB
- `corepack enable` manages pnpm versions consistently across environments
- The multi-stage build can reduce final image size by up to 90%
- `--frozen-lockfile` ensures dependency versions match exactly
- Only copying the `.output` directory prevents source code from being included in the production image
## Docker Compose Configuration
The `docker-compose.yml` file orchestrates our container setup:
```yaml [docker-compose.yml]
services:
nuxt-app:
build:
context: .
dockerfile: Dockerfile
container_name: nuxt-app
restart: always
ports:
- "3000:3000"
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:3000/api/hello" ]
interval: 30s
timeout: 10s
deploy:
resources:
limits:
memory: 1G
```
π‘ Key Features:
- restart: always ensures your app recovers from crashes
- The healthcheck endpoint verifies your application is truly running
- Resource limits prevent container memory leaks
- Port mapping allows direct access to your application
The healthcheck ensures your application is responding properly. If you want to add custom health endpoints, create an API route in your Nuxt app:
```ts [server/api/hello.ts]
export default defineEventHandler(() => {
return 'Hello World!'
})
```
## Automated Builds with GitHub Actions
Here's a sophisticated GitHub Action that builds and pushes images when you create a tag or trigger it manually:
```yaml [.github/workflows/build-and-push.yml]
name: Build and Push Portfolio Docker Image
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Version tag (ex: v1.0.0)'
required: true
type: string
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=tag
type=raw,value=${{ inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' }}
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
```
π‘ Workflow Features:
- It triggers on git tags (v1.0.0, v2.0.0, etc.)
- Supports manual triggers with custom version tags
- Uses GitHub's cache to speed up builds
- Automatically tags images with both version and latest tags
- Use the repository's name as the image name (update `IMAGE_NAME` if needed)
To use this setup:
1. Publish a new release with a version tag (v1.0.0, v2.0.0, etc.) in your GitHub repository or push a new tag: `git tag v1.0.0 && git push --tags`
2. Or manually trigger the workflow from GitHub's Actions tab Your images will be available at ghcr.io/yourusername/your-repo\:v1.0.0
π‘ Production Tips:
- Always use specific version tags in production
- Set up monitoring for the health check endpoint
- Configure proper logging
- Use environment variables for configuration
- Set up SSL/TLS termination
## (Bonus) Deploying with Coolify
With your Docker image automatically published to GitHub Registry, deploying with Coolify becomes straightforward:
1. Connect to your Coolify instance
2. Create a new service using your container image
3. Set `ghcr.io/yourusername/your-repo:latest` as the image source
4. Configure your environment variables
5. Deploy!
π‘ **Pro Tip**: Use semantic versioning tags (v1.0.0) in production instead of 'latest' for better stability and rollback capabilities.
You can find a complete working example in the [Canvas repository](https://github.com/HugoRCD/canvas){rel=""nofollow""}, one of my open-source projects. And an even more complex one in the [Shelve's repository](https://git.new/shelve){rel=""nofollow""}. Shelve is a complex but understandable project monorepo.
See it in action here: {rel=""nofollow""}
Remember that while Nuxt UI and Content are in alpha, they're actively developed and regularly updated. Keep an eye on the official releases for production use, and always test thoroughly before upgrading.
# How a Tweet Changed My Life
On December 17, 2024, at 10:12 in the morning, I posted a tweet.
Nothing special. Three sentences, a sweating emoji, a green heart. I was looking for a Nuxt internship to finish my degree, I couldn't find one, and a friend had just told me over coffee: "Why don't you just post something on Twitter?"
Two weeks later, I was working on Nuxt. Six months later, I was joining Vercel. A year later, I was living in London.
## One week, at fourteen
It starts with a work-experience week. In France, around fourteen, you spend a week shadowing an adult at their job. A family friend was a developer, so I spent mine with him. That's where I wrote my first HTML pages.
I don't know how to explain what it does to you, at that age, to watch something appear on a screen that you built out of lines of text. You type, and something exists that didn't before. I never really stopped after that.
As a teenager I touched a bit of everything. A lot of cyber-security at first. Then, like a lot of people, I wanted to make some money. The year I turned eighteen, in 2019, I started building websites as a freelancer. WordPress first, then hand-coded sites, in almost pure HTML, with a bit of PHP for templating so I could reuse chunks of pages. I didn't have the word for it yet, but I was already looking for components.
## A coding school, a company, and Vue
After high school I knew I wanted to be a developer, so I went to [Epitech](https://www.epitech.eu){rel=""nofollow""}, a coding school in France. Internships start in year one, and I landed at a company running on PHP and [Vue](https://vuejs.org){rel=""nofollow""}.
It was the first time I saw real PHP, MVC, a production codebase. But mostly, it was the first time I saw Vue. This was the Options API era, the [Composition API](https://vuejs.org/guide/extras/composition-api-faq){rel=""nofollow""} didn't exist yet. And still, it was completely obvious. The way code *should* be written was right there in front of me. I wanted to rewrite everything in the company. I didn't have the skills yet, but I'd fallen in love with the ideas.
I stayed at that company for a little over three years, on a work-study program alongside school.
## Nuxt 3, or: Lego
I'd tried Nuxt before version 3, and I didn't get it. Why was there a dev server *and* my app? What was it giving me? I gave up and stayed on Vue.
Then [Nuxt 3](https://nuxt.com/blog/v3){rel=""nofollow""} came out. [Modules](https://nuxt.com/modules){rel=""nofollow""}, [layers](https://nuxt.com/docs/getting-started/layers){rel=""nofollow""}, composability, the new branding. Everything fit together, and it was beautiful. And something clicked that goes back way before code.
As a kid I spent years on Lego. I still love it. I've always been someone who likes to build, and to build *well*. Nuxt is exactly that: bricks. You make a module, a composable, a layer, and you reuse it in the next project. After one project, the second one goes faster. After ten small projects, you can build a big one much faster. Nuxt is Lego. That's why I never left.
From that moment on, I built every school project in Nuxt, whenever I could. School often wanted us to try different languages, different stacks, so I asked. Explicitly, every time: can I do this one in Nuxt? I wanted to get better at it, and I already knew it was what I wanted to do later. It became an obsession.
And I loved going further than the brief. More concepts, more features, more bricks I could reuse in the next project. One of the first was [Helpr](https://helpr.hrcd.fr){rel=""nofollow""}, a full-stack [Zapier](https://zapier.com){rel=""nofollow""}-like. You create triggers, you chain reactions, you build workflows. It was a big application for the level I had at the time, and I poured hours and days into it.
But the ambitious part was somewhere else. This was the very beginning of ChatGPT, the [OpenAI API](https://platform.openai.com){rel=""nofollow""} meant the davinci models, and there was no such thing as structured output. Today, with the [AI SDK](https://ai-sdk.dev){rel=""nofollow""}, you hand the model a [Zod](https://zod.dev){rel=""nofollow""} schema and say "give me exactly this back". Back then, none of that existed. And I still got it to work, more or less: you described the workflow you wanted, in plain English, and Helpr generated it for you. Trigger, reactions, the whole thing.
Then there were the small AI touches sprinkled on top. The one that impressed people most, and me, was this: an email lands in your Gmail, and Helpr drafts the reply. Nothing special today. But it needed a prompt so the system knew what kind of draft to write, and I'd even added a button to improve that prompt for you. Small things, and every one of them felt like *this is the future*.
An AI-native Zapier, in 2023. Looking back, it was ahead of its time. Maybe I should have kept going, actually.
## Selling, then giving
Towards the end of my freelance years I had the idea everyone has: build templates and sell them. A little store, a few products, passive income.
It didn't work, and more importantly it wasn't what I wanted. I was getting closer and closer to the Nuxt ecosystem, which has this philosophy where you *give* the code away. So I tried.
I built my first modules. Then I built [Canvas](https://canvas.hrcd.fr){rel=""nofollow""}, my first Nuxt portfolio template. It did well, it got listed on [nuxt.com](https://nuxt.com/templates){rel=""nofollow""} and then on [Nuxt Studio](https://nuxt.studio){rel=""nofollow""}. And it's the first time [SΓ©bastien](https://x.com/Atinux){rel=""nofollow""}, the creator of Nuxt, sent me a DM.
You have to understand where I was at that point. I was a fan. Not a casual one. And here was the person who built the thing I'd been obsessing over for two years, writing to me about something I'd made.
It's only later that I understood what that moment really was: a foot in the door. The first time I felt like I was starting to belong to something. I think almost everyone in the Vue and Nuxt community has a version of that moment, and I don't think it's a coincidence.
Two months later, at the end of February, I started [Shelve](https://shelve.cloud){rel=""nofollow""}.
Originally Shelve was tiny. [Vercel](https://vercel.com){rel=""nofollow""} was too expensive for me to use with a team, and I just wanted the equivalent of [`env pull` / `env push`](https://vercel.com/docs/cli/env){rel=""nofollow""} to share environment variables. A weekend project, on paper.
But every time I start something, I go too far. And this time, I went further than ever, because something else was happening at the same time.
I was arriving on [Twitter](https://x.com/hugorcd){rel=""nofollow""}. Not just to post, but to watch. I'd started following design Twitter, the people who ship screen recordings of a hover state, a transition, a loading animation, and get thousands of likes for it. [Fey](https://fey.com){rel=""nofollow""} was the one that stuck with me. The level of detail in that app was absurd, and I couldn't look away. [Linear](https://linear.app){rel=""nofollow""} was the other obvious one, the reference everyone was chasing for design. And [Raycast](https://www.raycast.com){rel=""nofollow""}, for something different: not how it looked, but how it felt to use. The interactions, the speed, the DX.
That's the first time I understood the word *craft*. Until then, code was lines and ideas. Something works or it doesn't, and you move on. Suddenly it was closer to sculpture. You're carving something out of rock, and every detail counts, including the ones nobody will consciously notice.
Shelve is where I put all of that. A full-stack Nuxt app with [Nitro](https://nitro.build){rel=""nofollow""} behind it. Branding I did by hand. A caching layer I actually thought about. A CLI. GitHub sync. Every empty state, every transition, every error message, considered. I gave myself to that project in a way I hadn't before, and over time it became my reference for what a good Nuxt project looks like. A blueprint I still hand to people who want to build good apps.
And I was showing it. That's the other thing that started with Shelve. I posted everything: screenshots, animations, modules, templates, my first npm packages. Every small win, every new brick. [Daniel](https://bsky.app/profile/danielroe.dev){rel=""nofollow""} started following me. SΓ©bastien too. He'd like a post here and there, and every time, it felt like a lot.
And of course, nothing took off. Ten likes, sometimes fewer. It's hard to keep posting when nobody answers. I kept going anyway.
## September 2024
A little over three years after I joined, the company let me go. It's September 2024.
I find myself with a bit of money, because in France you get support in that situation, a lot of time, and a school telling me it's fine if I don't find a new placement right away.
So for four months I work flat out. On Shelve, on my side projects, and I post everything I make. I push hard, because I tell myself I might never get a window like this again, at this age, to do it.
But you can't live on severance forever. At some point money has to come from somewhere, and I could see it getting complicated. And I like working with a team, being around people.
So I look. Companies doing Vue, doing Nuxt, doing what I love, in France. And I find nothing. LinkedIn goes nowhere. Everyone is hiring [React](https://react.dev){rel=""nofollow""} developers. A month and a half goes by like that.
## The coffee
One day I'm at a cafΓ© with a friend. He's talking about everything I'm doing on Twitter, and he says: "Why don't you just post something on Twitter?"
Writing it down, I realise how dumb it sounds. But that's what happened. I hadn't thought of it, or hadn't dared, I don't remember. I tell myself: either way, I've got nothing to lose.
So I post [this](https://x.com/hugorcd/status/1868962514861785234){rel=""nofollow""}:
:screenshot{alt="The tweet: Looking for a @nuxt_js position for my final internship and wow - they're hard to find! Feels like everyone's hiring React devs. Curious: how many of you are actually using Nuxt at work?" href="https://x.com/hugorcd/status/1868962514861785234" src="https://hugorcd.com/images/writing/tweet-nuxt-internship.png"}
And then I get a message from SΓ©bastien.
One question: "What are the dates of your internship?"
I answer right away, without really understanding what's happening. I give him the dates. He replies with a Google Meet link.
My hands were shaking when I clicked it. The creator of Nuxt, the person whose work I'd been studying for two years, was about to get on a call with me. I had no idea, that day, that I was looking at the moment my life would split in two.
We talk for an hour. The kind of call where everything makes sense, where you feel like the person in front of you already knows what you're about. And at the end, he says it: "OK, you're in."
On January 6, 2025, I start at [NuxtLabs](https://nuxtlabs.com){rel=""nofollow""}.
## Six months at NuxtLabs
I meet the team. I start by working only on [Nuxt UI](https://ui.nuxt.com){rel=""nofollow""}, and a good part of what I did in those first months ended up in [Nuxt UI v4](https://nuxt.com/blog/nuxt-ui-v4){rel=""nofollow""}, the release that merged Nuxt UI and Nuxt UI Pro into a single library.
Getting paid to do open source is the best job in the world. I mean it. You build things that have impact, people take you seriously, they give you feedback. And for a developer, feedback is everything: being told whether what you make is good or not. So when on top of that the feedback is "I love what you're doing", it's a kind of fuel I'd never felt before.
Then, at the end of February, NuxtLabs' designer left. Suddenly there was no designer, and I stepped into the gap. Figma, the brand, the landing pages, everything visual on the Nuxt front. I loved every second of it. I was the one implementing [the new nuxt.com landing page](https://nuxt.com){rel=""nofollow""}, and I remember the feeling of shipping something that millions of people would see. This wasn't a side project anymore. This was the front door of Nuxt.
In March, [Vue.js Amsterdam](https://vuejs.amsterdam){rel=""nofollow""}. I see the whole team in person for the first time. It's also my first tech conference, and I find myself speaking English, surrounded by the Vue and Nuxt community I've loved for years. I'd been calling this a dream for years. It stopped being the right word around then.
And Twitter, meanwhile, starts to take off. More and more people know what I do, like it, support me. Some of them were there when my posts got six likes, and they're still here today. I notice. Thank you.
Over the months that followed, my role kept drifting outward. AI was becoming impossible to ignore, and I was getting pulled towards it: agent workflows, [MCP](https://modelcontextprotocol.io){rel=""nofollow""}, what it means for a framework to be usable by an AI. I did less Nuxt UI and more of everything else. [Nuxt Studio](https://nuxt.studio){rel=""nofollow""}, [Docus](https://docus.dev){rel=""nofollow""}, the overall story of Nuxt and AI. A satellite role, in a way, and one I only got because the team trusted me to go and find the next thing.
## "We're joining Vercel"
A month or two after Amsterdam, SΓ©bastien talks to us. Privately first, then all of us: Vercel is acquiring NuxtLabs, and we're joining Vercel.
I need to explain what that meant to me.
During my studies, when I imagined what came next, there were three branches. Start my own project, my own company. Join a product I love, at the time [Linear](https://linear.app){rel=""nofollow""}, [Raycast](https://www.raycast.com){rel=""nofollow""}, [Vercel](https://vercel.com){rel=""nofollow""}, the kind of company that makes a developer dream with its design and its DX, and that I'd been using for years. Or the one I wanted in my gut: work on Nuxt.
And right there, two of those three branches had just merged. I was going to work on Nuxt, *at* Vercel.
I'd already run out of the word "dream" in Amsterdam. I still don't have a better one for this.
The months that followed were a lot. Contracts, visas, paperwork, and one decision bigger than the rest: joining Vercel meant leaving Nice and starting everything over in London. I'd wanted to live abroad for a long time, so it wasn't a sacrifice. It was the excuse I'd been waiting for. I don't regret it for a second.
At the end of June, I graduate. On July 8, 2025, ten days later, [the announcement goes public](https://vercel.com/blog/nuxtlabs-joins-vercel){rel=""nofollow""}, and I walk into Vercel. I finished school one week and started at Vercel the next.
## Making your own luck
So yes, a tweet changed my life. But if you take one thing away from all this, I'd like it to be this.
It was luck. I'm not going to pretend otherwise. But I think everything in life rests a little on luck, and that's not a bad thing. It doesn't mean you're *a lucky person*. It means you have to make your luck.
If you want to go far, you have to multiply the entry points. The more you post, the more you show, the more you build in public, the more doors you create that luck can walk through. For years, every one of those doors stayed shut. Ten likes. Six likes. And one day, everything lines up.
Jason Roberts has a name for this, and [his post about it](https://www.codusoperandi.com/posts/increasing-your-luck-surface-area){rel=""nofollow""} is worth five minutes of your time.
::quote{author="Jason Roberts"}
Luck surface area: the amount of luck you get is proportional to what you do, multiplied by how many people you tell about it.
::
The December tweet didn't work because it was well written. It worked because SΓ©bastien and Daniel were already following me. Because they'd seen Canvas, Shelve, the modules, the screenshots, the animations, the hundred posts with six likes. By the time I asked, the answer had been building for two years.
You can be the best developer on the planet (not saying I am, but you get the idea). If nobody sees your work, it doesn't exist. Not to the people who could change something for you.
What happened after that deserves its own article. It's called *One year at Vercel*, and it's coming next.
# How Raycast Became My Ultimate Sidekick ?
Hey there, productivity enthusiasts! Let me take you on a journey through the magical land of Raycast β an app that has completely revolutionized my workflow and made me wonder how I ever survived without it. Get ready for a rollercoaster ride filled with productivity hacks, time-saving tricks!
## Snippets Magic:
Tired of typing the same thing over and over again? Say no more! With Raycast's snippet feature! Whether it's your lengthy email signature, those never-ending Unix commands, or the perfect code snippet you use in every component, Raycast has got your back. For all those developers who have made the right career move and are on Nuxt, I've also written an article on the subject :prose-a[5 raycast snippets for Nuxt]{href="https://hugorcd.com/writing/5-amazing-raycast-nuxt-snippets"} .
## Quicklinks, Warp Speed Navigation:
Tired of navigating through your 'Dev' folder every single time only to end up opening your portfolio with a 'code .' command? Well, fret no more! With Raycast's Quicklinks, you can open anything, anywhere, lightning-fast. No more unnecessary folder diving!
All my current projects can be opened directly in WebStorm from Raycast.
## AI Wizardry:
Why bother with a dozen different AI services when Raycast brings the power of AI right to your fingertips? Translate text, summarize articles, generate ideas based on what you're reading, squash bugs in your code β you name it, Raycast's got it covered.
I personally set the "Fix spelling and grammar" to the shortcut β₯ β₯ to never make spelling mistakes again.
I also use a lot my custom AI Command "Refacto" to make my code simpler and more maintainable. I simply select my code and run the command, then click on enter once the ia has finished its work and my new, clean, optimized code automatically replaces the old one. But also "Type to fake data" to generate fake data to test my api directly by selecting a type or interface! I made a tweet about it -> :prose-a[π₯ Easy fake data]{href="https://x.com/HugoRCD__/status/1755528539309326706?s=20"}
## Infinite Clipboard:
Ever wish you could retrieve something you copied ages ago? With Raycast's Infinite Clipboard, you'll never lose your clipboard again. It's like having a photographic memory for your clipboard!
## β¨Theβ¨ Emoji Picker:
Say goodbye to boring emoji selectors and hello to the emoji matrix of your dreams! With Raycast's emoji picker, you can express yourself in style faster than you can say "ππ»π." Whether you're feeling π or π‘, there's an emoji for every occasion β and finding them has never been easier or more fun!
## Extensions, one shortcut to rule them all:
Who needs a gazillion different apps cluttering up their system when Raycast's got a whole arsenal of extensions ready to go? Raycast's extensions are like Swiss Army knives for your workflow β They do it all: from creating tickets to generating Lorem Ipsum text, to fixing all your CORS errors. Okay, maybe not the last one, but who knows, maybe in the future, Raycast teams seem to work magic with every update.
Here is a "small" list of my favorite extensions and their installer links:
- **Linear**: Manage projects, create tickets, and stay on top of your to-do list with ease.
:prose-a[Install Here]{href="https://www.raycast.com/linear/linear"}
- **GitHub**: Create branches, manage pull requests, and navigate repositories seamlessly.
:prose-a[Install here]{href="https://www.raycast.com/raycast/github"}[](https://www.raycast.com/raycast/github){rel=""nofollow""}
- **Dub.sh**: Shorten URLs instantly with Dub.sh. Simplify sharing and keep your messages clean and concise.
:prose-a[Install here]{href="https://www.raycast.com/quuu/dub-link-shortener"}
- **Arc Search**: Explore the web with Arc Search. Conduct searches directly through the Arc browser for quick and efficient browsing. I use the ββ shortcut to quickly open arc search with my latest opened tabs.
:prose-a[Install Here]{href="https://www.raycast.com/the-browser-company/arc"}
- **Ray.so**: Turn code into images with Ray.so. Showcase your code snippets visually and add flair to your projects.
:prose-a[Install Here]{href="https://www.raycast.com/garrett/ray-so"}
- **Word Count**: Track document lengths with Word Count. Keep tabs on word counts for essays, reports, and more.
:prose-a[Install Here]{href="https://www.raycast.com/itsmingjie/word-count"}
- **Lorem Ipsum**: Generate placeholder text with Lorem Ipsum. Perfect for design mockups and content placeholders.
:prose-a[Install Here]{href="https://www.raycast.com/AntonNiklasson/lorem-ipsum"}[](https://www.raycast.com/AntonNiklasson/lorem-ipsum){rel=""nofollow""}
- **Floating Notes**: Capture your ideas on the fly with the Floating Notes extension. Whether you're brainstorming or jotting down a quick reminder, this tool has got your back. (Built-in)
- **Node version Manager**: Manage Node.js versions with Node Version Manager. Switch between versions seamlessly.
:prose-a[Install Here]{href="https://www.raycast.com/andresmorelos/node-version-manager"}[](https://www.raycast.com/andresmorelos/node-version-manager){rel=""nofollow""}
- **Remove.bg**: Say goodbye to pesky backgrounds with the Remove.bg Background Remover extension. Clean up your images and let your subjects shine.
:prose-a[Install Here]{href="https://www.raycast.com/maantje/remove-background"}[](https://www.raycast.com/maantje/remove-background){rel=""nofollow""}
- **ScreenOCR**: Extract text from images with ScreenOCR. Convert images to editable text quickly.
:prose-a[Install Here]{href="https://www.raycast.com/huzef44/screenocr"}[](https://www.raycast.com/huzef44/screenocr){rel=""nofollow""}
- **Vercel**: Manage deployments effortlessly and keep an eye on them.
:prose-a[Install Here]{href="https://www.raycast.com/vercel/vercast"}[](https://www.raycast.com/vercel/vercast){rel=""nofollow""}
- **Lucide / Heroicons**: Find icons with Lucide and Heroicons. Perfect for web and app design.
:prose-a[Install Lucide Here]{href="https://www.raycast.com/Sn0wye/lucide-icons"}
/
:prose-a[Install Heroicons Here]{href="https://www.raycast.com/johndoe123789/heroicons"}
- **Summarize Youtube Videos**: Get video summaries with Summarize Youtube Videos.
:prose-a[Install Here]{href="https://www.raycast.com/iKasch/summarize-youtube-video-with-ai"}
- **Kill Process**: Say goodbye to frozen programs
:prose-a[Install Here]{href="https://www.raycast.com/rolandleth/kill-process"}[](https://www.raycast.com/rolandleth/kill-process){rel=""nofollow""}
:br
So there you have it, folks! Raycast isn't just an app β it's a productivity powerhouse that will change the way you work forever. Whether you're a developer, designer, or just someone who wants to get stuff done faster, Raycast has something for everyone. So what are you waiting for? Trust me, your productivity levels will thank you later!
And to help you make the most of Raycast AI and take your experience to the next level, here are some links for you to enjoy a free month trial !
- {rel=""nofollow""}
- {rel=""nofollow""}
- {rel=""nofollow""}
- {rel=""nofollow""}
- {rel=""nofollow""}
- {rel=""nofollow""}
The article is all set! Let's celebrate your new workflow. If you already have Raycast, click here to wrap things up on a positive note!
[**Make it pop ! π**](raycast://extensions/raycast/raycast/confetti){.link}
# How To Securely Share Environment Variables With Your Team
Environment variables are the backbone of modern application configuration, containing sensitive data like API keys, database credentials, and service tokens. While they're crucial for development, managing them securely across a team can be challenging and risky. Let's explore why this matters and how to solve it effectively.
## The Hidden Dangers of Poor Environment Variable Management
### Security Breaches Waiting to Happen
Have you ever:
- Shared .env files through Slack or email?
- Accidentally committed sensitive credentials to Git?
- Used the same API keys across all environments?
- Stored passwords in plain text documents?
These common practices are security breaches waiting to happen. In fact, a recent study found that exposed credentials are responsible for over 80% of security incidents in cloud environments.
### The Real Cost of Weak Environment Management
Poor environment variable management leads to:
- Production outages from misconfigured variables
- Security breaches from exposed credentials
- Lost developer time dealing with environment setup
- Onboarding delays for new team members
- Compliance violations in regulated industries
## Best Practices for Secure Environment Management
### Security Fundamentals
- Implement environment-specific variables
- Use strong encryption for sensitive data
- Rotate credentials regularly
- Maintain strict access controls
- Keep comprehensive audit logs
### Version Control Guidelines
- Never commit real .env files to repositories
- Maintain detailed .env.example files
- Document all required variables
- Track configuration changes systematically
## Introducing Shelve: Modern Environment Management Done Right
Shelve is an open-source solution that transforms how teams handle environment variables. Here's what makes it special:
### Security Without Compromise
- End-to-end encryption for all sensitive data
- OAuth-based authentication
- Built-in secure value generator
- Zero plain-text storage
- Comprehensive audit logging
### Developer Experience First
- Powerful CLI for rapid workflows
- Drag & drop .env support
- Automatic formatting and validation
- Project templates for instant setup
- Intuitive web interface
### Built for Team Collaboration
- Team-based access control
- Secure variable sharing
- Detailed audit trails
- Simple member management
- Multi-environment support
### True Open Source
- 100% free and open source
- Self-hostable
- Transparent security
- Active community
- Regular updates
## Getting Started with Shelve
### 1. Install the CLI
```bash
npm install -g @shelve/cli
```
### 2. Create Your First Project
```bash
shelve create
```
## Why Teams Choose Shelve
- Cost-Effective: Free and open-source, unlike expensive commercial alternatives
- Security-First: Built with modern security practices at its core
- Developer-Centric: Designed by developers for real-world workflows
- Team-Ready: Built for collaboration from day one
- Future-Proof: Regular updates and active community
## Self-Hosting Options
Deploy Shelve on your infrastructure using:
- Docker
- Docker Compose
- Manual installation
All methods are documented in detail on GitHub.
## Take Control of Your Environment Variables
Stop risking your application's security with inadequate environment variable management. Shelve provides the security, simplicity, and collaboration features modern development teams need.
Ready to secure your environment variables?
[Get Started with Shelve on GitHub](https://git.new/variables){rel=""nofollow""}
[Try Shelve](https://shelve.cloud){rel=""nofollow""}
# Your story is worth telling
In the theater of content creation, there are many who, backstage, whisper a phrase tinged with doubt: ***"I'm not legitimate, others are so much better"***. This sound of insecurity, often played over and over in the minds of emerging creators, is the first act of a much larger work: the conquest of one's own legitimacy.
Imagine yourself standing at the edge of the stage, dazzled by the spotlight of self-judgment. Every creator goes through this. But instead of sinking into the shadows of self-deprecation, take a moment to listen to the whispers of the audience: the other creators. What you hear is not a cacophony of criticism, but a chorus of experiences and lessons.
This is where the magic happens. Instead of seeing the stage as a place for competition, turn it into a space for learning. Let other people's successes inspire you, **their mistakes teach you**. This is not imitation, but a creative harmony where you can find your own rhythm, your own melody.
**Your authenticity** ! is your most precious instrument. Play it with **confidence**. Every [note]{.no-link} of your experience, your perspective, resonates in a unique way with your audience. Authenticity is a creator's true opus, far more captivating than the exhausting quest for perfection.
Remember, **every creation is a rehearsal for the next**. There's no grand finale where everything has to be perfect. It's a continuous concert, where each performance is better than the last.
And in this showroom, you're not alone. Backstage, you'll find plenty of mentors, peers and admirers. They're there to encourage you, to guide you, to applaud your successes and support you in your doubts. This community is your chorus of support, turning fearful solos into courageous duets.
In the end, every curtain raised, every light turned on, is a step closer to accepting your own talent. The feeling of imposture dissipates not when you compare yourself to others, but when you recognize the unique beauty of your own performance. In this room, success is measured not just by the applause at the end, but by the courage to get up on stage and say: ***"Here's my story, listen to it"***.
# Clipboard #1
First edition. A few things that caught my attention this week β music I had on repeat, a video worth watching, and links I bookmarked.
## Listening
Two tracks that stayed on loop all week. The first one is pure ambient β the kind of thing you put on when you need to focus. The second is heavier, more cinematic.
:spotify-embed{url="https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT"}
:spotify-embed{url="https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b"}
## Watching
Fireship never misses. A sharp, fast breakdown of the current state of JavaScript frameworks. Worth the 10 minutes.
:video-embed{url="https://www.youtube.com/watch?v=Mus_vwhTCq0"}
## Reading
A few things I bookmarked and actually went back to read.
:link-card{description="Complexity very bad. Simple good. A collection of thoughts on software complexity." title="The Grug Brained Developer" url="https://grugbrain.dev"}
:link-card{description="Anthony Fu on why he prefers ESLint for formatting β and how the ecosystem evolved since." title="Why I don't use Prettier" url="https://antfu.me/posts/why-not-prettier"}
## Tools
- **Raycast** β Still the best launcher. Period. I finally set up all my custom scripts and AI commands, saves me minutes every day.
- **Linear** β Moved all my side project issues there. The speed is unmatched.
- **Zed** β Been trying it alongside Cursor. Blazing fast, but the plugin ecosystem isn't there yet.
## Random
::quote{author="Leonardo da Vinci"}
Simplicity is the ultimate sophistication.
::
That's it for this week. Short and sweet β future editions will probably be longer as I get into the habit.
---
# Plain site index (for LLMs)
Sections above may still contain MDC shortcuts (`::writing-list`, `::projects`, `:contact-links`). The lists below duplicate URLs and metadata in plain Markdown.
## Writing
- [How a Tweet Changed My Life](https://hugorcd.com/writing/how-a-tweet-changed-my-life) β From a layoff in Nice to Vercel in London, by way of Nuxt. The story of a tweet posted on a Tuesday morning in December, and of everything that made it work. (2026-09-02)
- [From Local to Production: Deploy the Latest Nuxt Stack with Docker](https://hugorcd.com/writing/from-local-to-production-containerizing-your-nuxt-app) β Learn how to properly containerize and deploy a Nuxt application using the latest versions of Nuxt UI and Content. Set up Docker with best practices, automate builds with GitHub Actions, and deploy your application anywhere. (2025-01-15)
- [How To Securely Share Environment Variables With Your Team](https://hugorcd.com/writing/how-to-securely-share-environment-variables-with-your-team) β Learn how to avoid critical security risks in environment variable management and discover how Shelve provides a modern, secure solution for development teams. (2024-10-24)
- [How Raycast Became My Ultimate Sidekick](https://hugorcd.com/writing/how-raycast-became-my-ultimate-sidekick) β Let me take you on a journey through the magical land of Raycast β an app that has completely revolutionized my workflow and made me wonder how I ever survived without it. (2024-03-05)
- [5 Amazing Raycast Snippets for Enhancing Your Nuxt (Vue) Projects](https://hugorcd.com/writing/5-amazing-raycast-nuxt-snippets) β Discover 5 powerful Raycast snippets that can transform your Nuxt and Vue development workflow, saving time and enhancing productivity. (2024-01-22)
- [You are not an impostor](https://hugorcd.com/writing/not-an-impostor) β Your story is worth telling, and you are not alone in this journey. Here's how to overcome the trap of perfection and embrace your authenticity. (2024-01-11)
## Clipboard
- [Clipboard #1](https://hugorcd.com/clipboard/2026-04-07) (2026-04-07)
## Works / projects
- **Personal Agent Template** (ecosystem): Open-source template for a durable personal AI agent β web chat, Slack, Linear, and long-term memory β https://personal-agent-template.vercel.app
- **Nuxt Connect Starter** (ecosystem): Minimal Nuxt starter for Vercel Connect β OAuth integrations hub with GitHub and Linear β https://nuxt-connect-starter.labs.vercel.dev
- **Nitro iMessage Agent** (personal): Durable iMessage AI agent template built with Nitro β https://github.com/vercel-labs/nitro-imessage-agent-template
- **F1 League** (personal): F1 prediction league with friends β https://f1.hrcd.fr
- **GitHub Tools** (featured): AI SDK tools for GitHub β https://github-tools.com
- **Evlog** (featured): Structured logging library for TypeScript β https://evlog.dev
- **Comark** (ecosystem): Streaming markdown parser with component support β https://comark.dev
- **Knowledge Agent** (ecosystem): File-system based AI agent template β https://chatsdk-knowledge-agent.vercel.app
- **Nuxt MCP Toolkit** (ecosystem): MCP server toolkit for Nuxt β https://mcp-toolkit.nuxt.dev
- **Nuxt Raycast Extension** (personal): Raycast extension for Nuxt β https://www.raycast.com/hugorcd/nuxt-ui
- **Nuppets** (personal): Nuxt & Vue snippets hub β https://nuppets.dev
- **Nuxt Visitors** (personal): Visitor tracking for Nuxt β https://github.com/HugoRCD/nuxt-visitors
- **Nuxt x Better Auth** (personal): Better Auth demo for Nuxt β https://better-auth.hrcd.fr/
- **Inkly** (personal): Email signature generator β https://inkly.email
- **@hrcd/eslint-config** (personal): ESLint config for TS, Vue & Nuxt β https://github.com/HugoRCD/eslint-config
- **Shelve** (featured): Environment variable manager β https://shelve.cloud/
- **HR Folio** (featured): My portfolio website β /
- **Nuxtlog** (personal): Changelog & blog template for Nuxt β https://nuxtlog.hrcd.fr
- **Currencia** (personal): Crypto tracker template β https://currencia.hrcd.fr
- **Canvas** (featured): Minimal portfolio template β https://canvas.hrcd.fr/
- **Helpr** (personal): Automation tools for workflows β https://helpr.hrcd.fr
- **Maison Hochard** (personal): Design & development agency β https://mh.hrcd.fr/
- **Nuxt.com** (ecosystem): The official Nuxt website β https://nuxt.com
- **Nuxt UI** (ecosystem): UI library for Nuxt & Vue β https://ui.nuxt.com
- **Docus** (ecosystem): Documentation framework for Nuxt β https://docus.dev