UNPKG

agent-rules-kit

Version:

Bootstrap of **Cursor** rules (`.mdc`) and mirror documentation (`.md`) for AI agent-guided projects.

420 lines (335 loc) 9.89 kB
--- description: Standard Architecture for Nuxt applications globs: <root>/nuxt.config.js,<root>/nuxt.config.ts,<root>/pages/**/*.vue,<root>/pages/**/*.js,<root>/pages/**/*.ts,<root>/components/**/*.vue,<root>/components/**/*.js,<root>/components/**/*.ts alwaysApply: false --- # Standard Nuxt Architecture This document outlines the standard architecture pattern for Nuxt.js applications in {projectPath}. ## Directory Structure The standard Nuxt architecture follows this directory structure: ``` {projectPath}/ ├── assets/ # Uncompiled assets (processed by webpack) │ ├── css/ # CSS/SCSS/LESS files │ └── images/ # Image files ├── components/ # Vue components │ ├── common/ # Shared/global components │ ├── ui/ # UI components (buttons, inputs, etc.) │ └── features/ # Feature-specific components ├── composables/ # Composition API functions ├── content/ # Markdown/JSON content (for @nuxt/content) ├── layouts/ # Page layouts │ ├── default.vue # Default layout │ └── error.vue # Error page layout ├── middleware/ # Navigation middleware ├── pages/ # Application pages & routing ├── plugins/ # Vue.js plugins ├── public/ # Static files (directly copied) ├── server/ # Server-side logic │ ├── api/ # API endpoints │ └── middleware/ # Server middleware ├── stores/ # State management (Pinia/Vuex) ├── types/ # TypeScript type definitions ├── utils/ # Utility functions ├── app.vue # Main application component ├── error.vue # Custom error page ├── nuxt.config.js # Nuxt configuration └── package.json # Project dependencies ``` ## Component Organization In the standard architecture, components are organized as follows: ### By Type/Role ``` components/ ├── common/ # Shared/global components │ ├── AppHeader.vue │ ├── AppFooter.vue │ └── AppSidebar.vue ├── ui/ # Reusable UI components │ ├── BaseButton.vue │ ├── BaseCard.vue │ ├── BaseInput.vue │ └── BaseModal.vue └── features/ # Feature-specific components ├── auth/ │ ├── LoginForm.vue │ └── SignupForm.vue ├── products/ │ ├── ProductCard.vue │ ├── ProductList.vue │ └── ProductDetail.vue └── checkout/ ├── CheckoutForm.vue └── PaymentOptions.vue ``` ## Data Flow The standard data flow in a Nuxt application follows this pattern: 1. **API Layer**: Server routes or external APIs 2. **State Management**: Pinia/Vuex stores or composables 3. **Component Logic**: Page or component setup/data 4. **UI Layer**: Templates and rendered HTML ### Data Fetching Pattern For Nuxt 3: ```ts // pages/products/[id].vue <script setup> const route = useRoute() const { data: product } = await useFetch(`/api/products/${route.params.id}`) </script> ``` For Nuxt 2: ```js // pages/products/_id.vue export default { async asyncData({ params, $axios }) { const product = await $axios.$get(`/api/products/${params.id}`); return { product }; }, }; ``` ## State Management ### Pinia (Recommended for Nuxt 3) ```ts // stores/products.js export const useProductStore = defineStore('products', { state: () => ({ items: [], loading: false, }), actions: { async fetchProducts() { this.loading = true; try { this.items = await $fetch('/api/products'); } finally { this.loading = false; } }, }, getters: { featuredProducts: (state) => state.items.filter((p) => p.featured), }, }); ``` ### Vuex (Nuxt 2) ```js // store/products.js export const state = () => ({ items: [], loading: false, }); export const mutations = { SET_PRODUCTS(state, products) { state.items = products; }, SET_LOADING(state, status) { state.loading = status; }, }; export const actions = { async fetchProducts({ commit }) { commit('SET_LOADING', true); try { const products = await this.$axios.$get('/api/products'); commit('SET_PRODUCTS', products); } finally { commit('SET_LOADING', false); } }, }; ``` ## API Layer ### Server Routes (Nuxt 3) ```ts // server/api/products/index.get.ts export default defineEventHandler(async (event) => { // Connect to database or external API const products = await db.products.findMany(); return products; }); // server/api/products/[id].get.ts export default defineEventHandler(async (event) => { const id = getRouterParam(event, 'id'); const product = await db.products.findUnique({ where: { id } }); if (!product) { throw createError({ statusCode: 404, message: `Product with ID ${id} not found`, }); } return product; }); ``` ### API Middleware (Nuxt 2) ```js // server-middleware/api/products.js const express = require('express'); const app = express(); app.use(express.json()); app.get('/products', async (req, res) => { // Handle request res.json([ /* products */ ]); }); app.get('/products/:id', async (req, res) => { // Handle request res.json({ id: req.params.id, name: 'Product' }); }); module.exports = app; ``` ## Authentication Pattern ### Auth Flow 1. User submits credentials 2. Credentials validated by server 3. JWT/session stored 4. Protected routes check auth status 5. Redirect if unauthenticated ### Implementation (Nuxt 3) ```ts // composables/useAuth.js export const useAuth = () => { const user = useState('user', () => null); const isAuthenticated = computed(() => !!user.value); async function login(credentials) { const response = await $fetch('/api/auth/login', { method: 'POST', body: credentials, }); user.value = response.user; // You might store token in cookie/localStorage // Or use auth.js/NuxtAuthHandler return navigateTo('/dashboard'); } function logout() { user.value = null; // Clear stored tokens return navigateTo('/login'); } return { user, isAuthenticated, login, logout, }; }; ``` ## Middleware Usage ### Auth Middleware (Nuxt 3) ```ts // middleware/auth.ts export default defineNuxtRouteMiddleware((to, from) => { const user = useState('user'); if (!user.value && to.path !== '/login') { return navigateTo('/login'); } }); ``` ### Auth Middleware (Nuxt 2) ```js // middleware/auth.js export default function ({ store, redirect, route }) { if (!store.state.auth.user && route.path !== '/login') { return redirect('/login'); } } ``` ## Composables Architecture Organize composables by feature or functionality: ``` composables/ ├── auth/ │ ├── useAuth.js # Authentication functions │ └── usePermissions.js # Permission checks ├── products/ │ ├── useProducts.js # Product data management │ └── useCategories.js # Category data management └── ui/ ├── useBreakpoints.js # Responsive breakpoint detection ├── useToast.js # Toast notification system └── useForm.js # Form handling utilities ``` ## Testing Structure ``` tests/ ├── components/ # Component tests │ ├── BaseButton.test.js │ └── ProductCard.test.js ├── composables/ # Composable tests │ └── useAuth.test.js ├── pages/ # Page tests │ └── index.test.js └── server/ # Server API tests └── products.test.js ``` Example component test: ```js import { describe, it, expect } from 'vitest'; import { mount } from '@vue/test-utils'; import BaseButton from '~/components/ui/BaseButton.vue'; describe('BaseButton', () => { it('renders the button with the correct text', () => { const wrapper = mount(BaseButton, { slots: { default: 'Click me', }, }); expect(wrapper.text()).toContain('Click me'); }); it('emits click event when clicked', async () => { const wrapper = mount(BaseButton); await wrapper.trigger('click'); expect(wrapper.emitted('click')).toBeTruthy(); }); }); ``` ## Configuration Architecture Organize your Nuxt configuration by logical groups: ```js // nuxt.config.js export default defineNuxtConfig({ // Core configuration app: { head: { title: 'My Nuxt App', meta: [{ name: 'description', content: 'My Nuxt App Description' }], }, }, // Module configuration modules: ['@pinia/nuxt', '@nuxt/content', '@nuxtjs/tailwindcss'], // Feature configuration content: { // Content module options }, // Environment configuration runtimeConfig: { apiSecret: process.env.API_SECRET, public: { apiBase: process.env.API_BASE || '/api', }, }, // Build configuration nitro: { // Server options }, vite: { // Vite options }, }); ``` ## Best Practices for Standard Architecture 1. **Consistent Component Organization** - Group by feature or type depending on project size - Use consistent naming conventions 2. **State Management Modularity** - Divide stores by domain/feature - Avoid a single monolithic store 3. **Minimalist Component Design** - Keep components focused on single responsibilities - Extract reusable logic to composables 4. **Server/Client Code Separation** - Clearly distinguish server-only and client-only code - Use appropriate server utilities for sensitive operations 5. **Typed Interfaces** - Define and use TypeScript interfaces for data structures - Enforce consistent data shapes across the application