agentsclimarketplace

My frontend conventions

Skill AGilbertDev/agilbertdev-recipes/skills/my-frontend-conventions

My reusable coding-agent conventions and a curated skill set, pulled into any project like a versioned package.

Install
npx -y skills add AGilbertDev/agilbertdev-recipes --skill my-frontend-conventions

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

AGilbertDev's frontend conventions for Nuxt/Vue projects — component and composable choices, solution priority, and icons. Use when building UI, components, or pages in a personal Nuxt project. Pairs with my-styling-conventions for Tailwind and theming.

SKILL.md

5.1 KB, as published. Nobody here has run it

Frontend conventions (Nuxt / Vue)

Solution priority

Reach for solutions in this order, and stop at the first that fits:

  1. Nuxt UI components and composables
  2. Nuxt core features
  3. Custom Vue
  4. Tailwind utilities for styling gaps

Look up the official docs and explain the reasoning rather than guessing. When naming a component or API, name it exactly (for example UFormField with a UInput inside) so it is easy to look up.

Components

  • Prefer Nuxt UI primitives (UButton, UCard, UForm, UModal, UTable, UInput, and so on) before building custom.
  • Vue 3 Composition API with <script setup>. Keep components small and composable; pull shared logic into composables.

Data mutations and cache invalidation

Always invalidate the client cache after a mutation. Any write that changes server state (a $fetch POST, PATCH, or DELETE) must be followed by refreshing whatever client-side cache reads that state, so the UI reflects the change without a full page reload.

  • Data loaded with useFetch or useAsyncData: call the returned refresh() after the write, or refreshNuxtData(key) for a shared key.
  • State that lives in the nuxt-auth-utils session (anything read off user): call fetch() from useUserSession() after the write so user re-reads.
  • State derived from the session once does not re-derive when user re-reads. A useState seeded from user (for example the useTheme light and dark ids) and the active i18n locale keep their first value, so re-apply them by hand in the same success handler by setting the useTheme state and calling setLocale. Refreshing the session alone leaves these looking reverted.
  • An optimistic local update is fine for responsiveness, but the authoritative refetch still has to run so the cache and the server agree.

Never rely on the next navigation or reload to pick up a change. A stale client cache after a mutation is a bug.

Server state with TanStack Query

Use TanStack Query (@tanstack/vue-query) for reading and writing server state, layered on Nuxt's data fetching. Register it once in a Nuxt plugin with SSR hydration, dehydrating on the app:rendered hook and hydrating on the client.

  • Query keys live in one factory file, app/queries/keys.ts, exported as a queryKeys object with a function per key. A key is never hand-typed at a call site, so the keys a mutation invalidates always match the queries that produced them.
  • Query and mutation composables live in app/composables/, auto-imported, named useXxxQuery and useXxxMutation. A page reads and writes server state through these composables rather than a bare $fetch.
  • Every mutation invalidates the affected query keys in onSuccess with queryClient.invalidateQueries. Session-backed state is not in the query cache, so it is still refreshed through useUserSession().fetch() in the same onSuccess, following the mutations section above.

Loading state on submit

Every form submit shows a loading state on its submit control while the write is in flight. Bind the submit UButton's :loading to the mutation's isPending, or to the local in-flight flag when the write is not a TanStack mutation, and keep the control disabled until it settles. A slow write is then never mistaken for a dead button and cannot be double-submitted.

Icons

  • Phosphor is the default set, via the Nuxt UI icon prop (i-ph-*). Match the icon weight to the text it sits with: use the -bold variants next to bold or large text so the glyph does not look thin, and scale the icon up as the text scales. Pick one weight family per project and stay consistent.
  • Simple Icons for brand and logo marks only (i-simple-icons-*).

Page composition

  • Build a long landing or portfolio page as one route that scrolls through sections, each its own component under components/home/ (hero, about, experience, and so on), assembled in the page. Keep the page file a thin list of those sections.
  • A small reusable SectionHeader component (a mono text-primary kicker plus the section h2) keeps headers consistent. Exactly one h1 (the hero), one h2 per section, in order.
  • For in-page anchor nav, keep the section ids in one composable (for example useSectionId) so the nav links and each <section :id> always agree. On a bilingual site make the ids locale-aware there (#a-propos / #about), and translate the current hash when toggling locale so the toggle stays on the same section.

Scroll reveal

  • Reveal sections on scroll with a small client plugin: add a js class to <html>, hide [data-reveal] elements only when that class is present (so a no-JS render still shows everything), then add an is-in class through an IntersectionObserver on mount and after each navigation. Stagger children with a --reveal-i custom property. Gate the whole effect behind prefers-reduced-motion.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.