agentleFS
chawkitariqchawkitariq/fidely/.claude/skills/coding-standards/SKILL.md

coding-standards

Skill0 starsChanged 8 months agoMITView on GitHub

Standards de codage à appliquer sur tout code écrit ou modifié dans Fidely. Déclencher quand : écriture ou revue de TypeScript/Vue, création de composable (useDB, useClient), ajout de fonction dans utils/, revue de types (Card, ClientData, CardFormData), JSDoc manquant. Mots-clés : TypeScript strict, any, import type, JSDoc, @param, @returns, <script setup>, defineProps, defineEmits, computed, uuidv7, zod, eslint, interface Card, interface ClientData.

120 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use everything-claude-code, everything-claude-code-conventions and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • InfopibeSkill

    everything-claude-code

    Also in 9 projects that use this

  • mryeastcodeSkill

    everything-claude-code-conventions

    Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

    Also in 8 projects that use this

  • niloykumarbarmanSkill

    agent-sort

    Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

    Also in 8 projects that use this

  • tpavanipradeepSkill

    nextjs-turbopack

    Next.js 16+ and Turbopack — incremental bundling, FS caching, dev speed, and when to use Turbopack vs webpack.

    Also in 15 projects that use this

  • CodeWithBehnamSkill

    dmux-workflows

    Multi-agent orchestration using dmux (tmux pane manager for AI agents). Patterns for parallel agent workflows across Claude Code, Codex, OpenCode, and other harnesses. Use when running multiple agent sessions in parallel or coordinating multi-agent development workflows.

    Also in 17 projects that use this

  • InfopibeSkill

    investor-outreach

    Draft cold emails, warm intro blurbs, follow-ups, update emails, and investor communications for fundraising. Use when the user wants outreach to angels, VCs, strategic investors, or accelerators and needs concise, personalized, investor-facing messaging.

    Also in 22 projects that use this

  • +1 more from Infopibe

The file

Files
SKILL.md

Skill : Standards de codage Fidely

Ces règles s'appliquent à tout code écrit ou modifié, sans exception.

Ressources disponibles

  • reference/jsdoc-examples.md — exemples JSDoc complets tirés du vrai code du projet
  • reference/typescript-patterns.md — interfaces réelles, patterns TypeScript du projet

1. TypeScript

  • strict: true activé via les configs auto-générées de Nuxt
  • Zéro any implicite ou explicite — typer toutes les interfaces
  • Exporter les interfaces depuis les composables qui les définissent :
    // app/composables/useDB.ts — interfaces réelles du projet
    export interface Card {
      id: string           // UUID v7
      title: string
      reward_points: number
      reward: string
      created_at: number   // timestamp ms
    }
    
    export interface ClientData {
      cards: Record<string, number>  // cardId → points
      last_seen: number              // timestamp ms
    }
  • Utiliser import type { ... } pour les imports de types seuls
  • Typer explicitement les retours de fonctions async :
    async function getAllCards(): Promise<Card[]> { ... }
    async function updatePoints(clientId: string, cardId: string, delta: number): Promise<number> { ... }
    async function addCard(data: Omit<Card, 'id' | 'created_at'>): Promise<Card> { ... }

2. ESLint & formatage

  • Pas de virgule finale (commaDangle: 'never')
  • Accolades style 1tbs (braceStyle: '1tbs')
  • Indentation 2 espaces (.editorconfig)
  • Pas de point-virgule superflu (defaults Nuxt ESLint)
  • Vérification obligatoire avant commit :
    pnpm lint       # 0 warning
    pnpm typecheck  # 0 erreur

3. Langue du code — anglais obligatoire

Tout le code est écrit en anglais, sans exception.

ÉlémentLangue
Noms de variables, fonctions, interfaces✅ Anglais
Commentaires inline (// ...)✅ Anglais
JSDoc (/** ... */)✅ Anglais
Messages d'erreur lancés par throw✅ Anglais
Textes UI affichés à l'utilisateur (labels, toasts, placeholders)🇫🇷 Français
// ❌ Ne pas faire
/** Retourne tous les points du client pour cette carte */
const current = client.cards[cardId] ?? 0 // points actuels

// ✅ Correct
/** Returns the client's current points for a given card. */
const current = client.cards[cardId] ?? 0 // current point balance

4. JSDoc — obligatoire

Toute fonction publique, composable, et interface exportée doit avoir un JSDoc. JSDoc rédigé en anglais (voir section 3).

Fonctions et composables

/**
 * Opens the `fidely` IndexedDB database (version 2) and returns the instance.
 * Creates the `cards`, `clients`, and `config` object stores if needed.
 * Result is cached — multiple calls return the same promise.
 *
 * @returns Promise resolved with the IDBDatabase instance
 */
async function openDB(): Promise<IDBDatabase> { ... }

/**
 * Adds or removes points for a client on a given card.
 * Implicitly creates the client if they don't exist yet.
 * Guarantees the balance never drops below 0 (Math.max).
 *
 * @param clientId - Client UUID (stored in IndexedDB config store)
 * @param cardId   - Loyalty card UUID
 * @param delta    - Points to add (positive) or remove (negative)
 * @returns New point balance for this client/card pair
 */
async function updatePoints(clientId: string, cardId: string, delta: number): Promise<number> { ... }

/**
 * Redeems a reward by deducting `rewardPoints` from the client's balance.
 * Preserves any surplus (e.g. 8 pts, threshold 6 → 2 pts remaining).
 *
 * @param clientId     - Client UUID
 * @param cardId       - Loyalty card UUID
 * @param rewardPoints - Points to deduct (= card.reward_points)
 * @returns Remaining balance after deduction
 * @throws Error 'Not enough points' if balance < rewardPoints
 */
async function consumeReward(clientId: string, cardId: string, rewardPoints: number): Promise<number> { ... }

Interfaces et types exportés

/**
 * Loyalty card created by a merchant.
 * Persisted in IndexedDB object store `cards` (keyPath: 'id').
 */
export interface Card {
  /** UUID v7 generated by uuidv7() */
  id: string
  /** Display name of the card (e.g. "Café du Coin") */
  title: string
  /** Number of points required to unlock the reward */
  reward_points: number
  /** Reward description (e.g. "1 café offert") */
  reward: string
  /** Creation timestamp in milliseconds */
  created_at: number
}

/**
 * Client loyalty data across all cards.
 * Persisted in IndexedDB object store `clients` (key = clientId UUID).
 */
export interface ClientData {
  /** Map of cardId → accumulated points */
  cards: Record<string, number>
  /** Last update timestamp in ms */
  last_seen: number
}

Composables

/**
 * Main composable for all Fidely IndexedDB operations.
 * Single entry point — never call `indexedDB` directly from a page or component.
 *
 * Object stores: `cards` (loyalty cards), `clients` (points per client),
 * `config` (app settings, including client_id).
 *
 * @example
 * const { getAllCards, addCard, updatePoints } = useDB()
 * const cards = await getAllCards()
 */
export function useDB() { ... }

/**
 * Manages the unique client identifier (stable UUID, generated once).
 * Stored in IndexedDB object store `config` under the key `client_id`.
 *
 * @example
 * const { getOrCreateClientId } = useClient()
 * const id = await getOrCreateClientId() // same value on every call
 */
export function useClient() { ... }

Règles JSDoc

ÉlémentJSDoc requis
Fonction exportée depuis un composable✅ Oui
Interface / type exporté✅ Oui
Composable lui-même (export function useXxx)✅ Oui
Fonction interne locale non exportée > 10 lignes✅ Oui
Fonction utilitaire dans utils/✅ Oui
Getter/computed trivial (computed(() => props.id))❌ Non
Handler inline évident (function closeModal())❌ Non

5. Structure d'un composable

/**
 * [Description du composable et de sa responsabilité]
 *
 * @example
 * const { items, loadItems } = useFeature()
 */
export function useFeature() {
  const items = ref<Item[]>([])

  /**
   * Charge les items depuis IndexedDB.
   * Ne fait rien côté serveur (SSR guard).
   */
  async function loadItems(): Promise<void> {
    if (import.meta.server) return   // guard SSR obligatoire si browser API
    // logique
  }

  return { items, loadItems }
}

Règles :

  • Nom : useXxx en camelCase — auto-importé par Nuxt
  • Exporter les interfaces utilisées par plusieurs fichiers depuis le composable
  • Guard SSR : if (import.meta.server) return avant tout appel à indexedDB, localStorage, document, window
  • Pas de side-effects au niveau module (pas de fetch ou indexedDB.open() au top-level)
  • useDB() est le seul point d'entrée pour IndexedDB

6. Structure d'un composant Vue

Ordre obligatoire dans <script setup lang="ts"> :

<script setup lang="ts">
// 1. imports de types uniquement
import type { Card } from '~/composables/useDB'

// 2. props — générics, jamais options object
const props = defineProps<{
  card: Card
  loading?: boolean
}>()

// 3. emits — tuple syntax
const emit = defineEmits<{
  saved: [card: Card]
  cancelled: []
}>()

// 4. composables Nuxt (auto-importés)
const toast = useToast()

// 5. state local
const isOpen = ref(false)

// 6. computed — jamais de logique dans le template
const label = computed(() => props.loading ? 'Chargement…' : 'Enregistrer')

// 7. fonctions (async avec try/catch + feedback toast)
async function handleSave(): Promise<void> {
  // logique
}
</script>

Règles :

  • <script setup lang="ts"> toujours en premier, avant <template>
  • Props optionnelles avec ? — valeur par défaut dans un computed ou ??
  • Jamais defineProps avec l'objet options (style Vue 2)
  • Jamais de logique conditionnelle complexe dans {{ }} — utiliser computed
  • Emits en camelCase côté émission, kebab-case dans le parent (@points-changed)

7. UUID — utiliser uuidv7 exclusivement

// app/utils/uuid.ts — helper du projet
import { uuidv7 } from 'uuidv7'

export function generateUUID(): string {
  return uuidv7()
}
// ❌ Ne pas utiliser crypto.randomUUID()
const id = crypto.randomUUID()

// ✅ Utiliser generateUUID() du projet
const { generateUUID } = await import('~/utils/uuid')
const id = generateUUID()

Pourquoi uuidv7 ? UUID v7 sont triés chronologiquement → meilleure indexation IndexedDB et débogage facilité.


8. Auto-imports Nuxt — ne jamais importer manuellement

// ❌ Inutile
import { ref, computed, onMounted } from 'vue'
import { useRoute, navigateTo } from '#app'

// ✅ Correct — juste utiliser directement
const route = useRoute()
const count = ref(0)

Auto-importés : ref, computed, reactive, watch, watchEffect, onMounted, onBeforeUnmount, useRoute, useRouter, navigateTo, useToast, useHead, useSeoMeta, et tous les composables/utils du dossier app/


9. Checklist avant de marquer une tâche ✅

pnpm typecheck   # 0 erreur TypeScript
pnpm lint        # 0 warning ESLint
pnpm vitest run  # 0 test en échec
[ ] Code et JSDoc rédigés en anglais (textes UI en français)
[ ] Aucun `any` explicite ou implicite
[ ] JSDoc présent sur toutes les fonctions/interfaces exportées
[ ] Guards SSR en place sur toutes les browser APIs
[ ] Retours de fonctions async explicitement typés
[ ] Ordre des blocs dans <script setup> respecté
[ ] Props/emits avec générics (pas options object)
[ ] Jamais de logique dans {{ }} — utiliser computed
[ ] uuidv7() utilisé via generateUUID() — pas crypto.randomUUID()

Confirmation en fin de tâche

Après application de ces standards, confirmer :

✅ coding-standards appliqués

  • TypeScript : [0 any / types vérifiés]
  • JSDoc : [fonctions/interfaces documentées]
  • ESLint : [pnpm lint → 0 warning]
  • Structure Vue : [ordre des blocs respecté]

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.