AlexOp Newsletter: Building Smarter with AI, GraphQL, and Vue

๐Ÿ‘‹ Intro:
This week, I wrapped up Chip Huyenโ€™s AI Engineering, a fantastic deep dive into building real-world AI systems with foundation models. Itโ€™s sparked a new obsession: learning everything I can about AI. Iโ€™ve also decided to start blogging about GraphQL + Vue, drawing from a year of hands-on experience at work.

๐Ÿ“Œ New Posts:

๐Ÿ”— 3 Links I Loved:

  • Distributed Tracing with OpenTelemetry - Part I (https://signoz.io/blog/opentelemetry-distributed-tracing-part-1/) โ€“ A clear introduction to OpenTelemetry and distributed tracing, perfect for understanding how to monitor complex systems effectively.

  • DeepWiki: AI-Powered GitHub Documentation (https://deepwiki.com/vuejs/core) โ€“ DeepWiki transforms GitHub repositories into interactive, AI-generated wikis, making it easier to explore and understand codebases.

  • Vue 3 Snapshot Testing Tutorial (https://www.youtube.com/watch?v=PVqMzrt9r-Q) โ€“ A helpful video demonstrating how to write better snapshot tests for Vue 3 components using a plugin that improves snapshot readability and maintenance.

โšก One-Minute Tip:
Did you know you can save and reuse prompts in GitHub Copilot to supercharge your coding?

Here's how:
๐Ÿ‘‰ Prompt Files (*.prompt.md) let you create reusable prompts directly in your project. Just enable "chat.promptFiles": true in VS Code settings and create a .github/prompts folder. Inside it, write Markdown files with your custom prompts!

Example โ€” I built one for refactoring Vue components into inline composables:

# Inline Vue Composables Refactoring

Refactor the given Vue 3 `<script setup>` component to use **inline composables**, following Martin Fowler's Extract Function pattern.

## What is a Composable?
A composable is a function that leverages Vue's Composition API reactivity system. It must import and use at least one reactive feature from Vue (such as `ref`, `reactive`, `computed`, `watch`, etc.) to manage stateful logic.

## Instructions

1. **Identify related logic groups**  
   - State (`ref`, `reactive`, `computed`, etc.)  
   - Watchers (`watch`, `watchEffect`)  
   - Lifecycle hooks (`onMounted`, `onUnmounted`, etc.)
   - Async or sync functions (mutations, API calls)

2. **Extract each group into an inline composable**  
   - Declare a function inside the same `<script setup>` block named `useXyz()`, where `Xyz` clearly describes the concern (e.g. `useHiddenFolders`, `useFavoriteFolders`).  
   - Move related state, watchers, lifecycle hooks, and methods into that function.  
   - Return only the reactive variables and methods needed by the template.

3. **Update topโ€‘level code**  
   - Replace the original state/watchers/functions with calls to the new inline composables:  
     ```js
     const { foo, toggleFoo } = useFooLogic()
     ```
   - Keep imports at the top; composable definitions below all top-level code.

4. **Maintain file structure and functionality**  
   - Keep the `<script setup>` wrapper intact.  
   - Preserve all imports, type annotations, and existing behavior.
   - Ensure returned refs/reactive objects maintain their reactivity.

5. **Example**

   **Before refactoring**  
   ```js
   <script setup>
   import { ref, watch } from 'vue'
   import { useQuery, mutate } from 'vue-apollo'
   import FOLDERS_FAVORITE from '@/graphql/folder/favoriteFolders.gql'
   import FOLDER_SET_FAVORITE from '@/graphql/folder/folderSetFavorite.gql'

   async function toggleFavorite(currentFolder) {
     await mutate({ mutation: FOLDER_SET_FAVORITE, variables: { path: currentFolder.path, favorite: !currentFolder.favorite } })
   }

   const showHidden = ref(localStorage.getItem('show-hidden') === 'true')
   watch(showHidden, v => {
     if (v) localStorage.setItem('show-hidden', 'true')
     else localStorage.removeItem('show-hidden')
   })

   const favoriteFolders = useQuery(FOLDERS_FAVORITE, [])
   </script>
   ```

   **After refactoring**  
   ```js
   <script setup>
   import { ref, watch } from 'vue'
   import { useQuery, mutate } from 'vue-apollo'
   import FOLDERS_FAVORITE from '@/graphql/folder/favoriteFolders.gql'
   import FOLDER_SET_FAVORITE from '@/graphql/folder/folderSetFavorite.gql'

   const { showHidden } = useHiddenFolders()
   const { favoriteFolders, toggleFavorite } = useFavoriteFolders()

   function useHiddenFolders() {
     const showHidden = ref(localStorage.getItem('show-hidden') === 'true')
     watch(showHidden, v => {
       if (v) localStorage.setItem('show-hidden', 'true')
       else localStorage.removeItem('show-hidden')
     }, { lazy: true })
     return { showHidden }
   }

   function useFavoriteFolders() {
     const favoriteFolders = useQuery(FOLDERS_FAVORITE, [])
     async function toggleFavorite(currentFolder) {
       await mutate({ mutation: FOLDER_SET_FAVORITE, variables: { path: currentFolder.path, favorite: !currentFolder.favorite } })
     }
     return { favoriteFolders, toggleFavorite }
   }
   </script>
   ```

You can then attach this prompt in Copilot Chat by clicking the ๐Ÿ“Ž icon and selecting your saved prompt.
Perfect for keeping your refactoring consistent and saving mental energy!

๐Ÿ‘‰ Full guide if you want to set this up too: GitHub Docs โ€“ Adding Repository Custom Instructions for Copilot

P.S.
I'm just getting started! Next up, Iโ€™ll dive into how to make your Vue + GraphQL projects fully type-safe using GraphQL Codegen.

Best,

Alex