\bin\mongod.cfg`
+
+### Common Configuration Options
+```yaml
+# Network interfaces
+net:
+ port: 27017
+ bindIp: 127.0.0.1 # Only localhost
+
+# Storage
+dbPath: /data/db
+
+# Security
+security:
+ authorization: enabled # Enable authentication
+
+# Replication (for replica sets)
+replication:
+ replSetName: "rs0"
+
+# Performance
+storage:
+ journal:
+ enabled: true
+ wiredTiger:
+ engineConfig:
+ cacheSizeGB: 1 # Adjust based on available RAM
+```
+
+## Authentication
+
+### Create Admin User
+```javascript
+use admin
+db.createUser({
+ user: 'admin',
+ pwd: 'your-secure-password',
+ roles: [ { role: 'userAdminAnyDatabase', db: 'admin' } ]
+})
+```
+
+### Connect with Authentication
+```javascript
+const uri = 'mongodb://admin:your-secure-password@localhost:27017/admin';
+const client = new MongoClient(uri);
+```
+
+## Backup and Restore
+
+### Create Backup
+```bash
+mongodump --uri="mongodb://localhost:27017" --out=/backup/$(date +%Y%m%d)
+```
+
+### Restore from Backup
+```bash
+mongorestore --uri="mongodb://localhost:27017" /backup/20231015/mydb
+```
+
+## Monitoring
+
+### Basic Stats
+```javascript
+db.serverStatus()
+
+db.stats()
+
+// Collection stats
+db.collection.stats()
+
+// Current operations
+db.currentOp()
+```
+
+### Enable Profiling
+```javascript
+// Set profiling level (0=off, 1=slow, 2=all)
+db.setProfilingLevel(1, { slowms: 100 })
+
+// View profile data
+db.system.profile.find().pretty()
+```
diff --git a/docs/ui/bootstrap.md b/docs/ui/bootstrap.md
new file mode 100644
index 0000000..9d00bc8
--- /dev/null
+++ b/docs/ui/bootstrap.md
@@ -0,0 +1,529 @@
+# Bootstrap 5 Documentation
+
+## Table of Contents
+1. [Getting Started](#getting-started)
+2. [Layout](#layout)
+3. [Components](#components)
+4. [Utilities](#utilities)
+5. [Forms](#forms)
+6. [Icons](#icons)
+7. [Theming](#theming)
+8. [Customization](#customization)
+9. [Best Practices](#best-practices)
+
+## Getting Started
+
+### Installation
+
+#### CDN (Quick Start)
+```html
+
+
+
+
+
+```
+
+#### NPM
+```bash
+npm install bootstrap@5.3.0
+```
+
+#### Basic HTML Template
+```html
+
+
+
+
+
+ Bootstrap 5
+
+
+
+ Hello, Bootstrap 5!
+
+
+
+```
+
+## Layout
+
+### Container
+```html
+
+
+
+
+
+
+
+
+
+100% wide until small breakpoint
+100% wide until medium breakpoint
+100% wide until large breakpoint
+100% wide until extra large breakpoint
+100% wide until extra extra large breakpoint
+```
+
+### Grid System
+```html
+
+
+
Column 1
+
Column 2
+
Column 3
+
+
+
+
Main content (8/12)
+
Sidebar (4/12)
+
+
+
+
+
+```
+
+### Breakpoints
+| Breakpoint | Class Infix | Dimensions |
+|-------------|------------|------------|
+| X-Small | None | <576px |
+| Small | `sm` | ≥576px |
+| Medium | `md` | ≥768px |
+| Large | `lg` | ≥992px |
+| Extra large | `xl` | ≥1200px |
+| Extra extra large | `xxl` | ≥1400px |
+
+## Components
+
+### Buttons
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Cards
+```html
+
+

+
+
Card title
+
Some quick example text to build on the card title and make up the bulk of the card's content.
+
Go somewhere
+
+
+
+
+
+
+
+
Special title treatment
+
With supporting text below as a natural lead-in to additional content.
+
Go somewhere
+
+
+
+```
+
+### Navbar
+```html
+
+```
+
+### Modal
+```html
+
+
+
+
+
+
+
+
+
+
Modal body text goes here.
+
+
+
+
+
+```
+
+## Utilities
+
+### Spacing
+```html
+
+Margin all around (0.25rem)
+Margin top (1rem)
+Padding all around (1.5rem)
+Padding left and right (3rem)
+
+
+Responsive margin
+```
+
+### Text
+```html
+Start aligned text
+Center aligned text
+End aligned text
+
+Primary text
+Success text
+Danger text
+
+Bold text
+Italic text
+Uppercase text
+Truncated text with an ellipsis...
+```
+
+### Colors
+```html
+
+.text-primary
+.text-secondary
+.text-success
+.text-danger
+.text-warning
+.text-info
+.text-light
+.text-dark
+.text-muted
+
+
+.bg-primary
+.bg-success
+```
+
+## Forms
+
+### Basic Form
+```html
+
+```
+
+### Form Controls
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Form Validation
+```html
+
+```
+
+## Icons
+
+### Bootstrap Icons
+```html
+
+
+
+
+
+
+```
+
+## Theming
+
+### Color Modes
+```html
+
+
+
+
+
+
+```
+
+### Custom Colors
+```scss
+// Custom.scss
+// Override default variables before the import
+$body-bg: #000;
+$body-color: #fff;
+$primary: #0d6efd;
+$secondary: #6c757d;
+$success: #198754;
+
+// Import Bootstrap and its default variables
+@import '~bootstrap/scss/bootstrap';
+```
+
+## Customization
+
+### SASS Variables
+```scss
+// Customize colors
+$primary: #0074d9;
+$secondary: #6c757d;
+$success: #28a745;
+$info: #17a2b8;
+$warning: #ffc107;
+$danger: #dc3545;
+$light: #f8f9fa;
+$dark: #343a40;
+
+// Customize spacing
+$spacer: 1rem;
+$spacers: (
+ 0: 0,
+ 1: $spacer * .25,
+ 2: $spacer * .5,
+ 3: $spacer,
+ 4: $spacer * 1.5,
+ 5: $spacer * 3,
+ 6: $spacer * 4,
+ 7: $spacer * 5,
+ 8: $spacer * 6,
+);
+
+// Customize container sizes
+$container-max-widths: (
+ sm: 540px,
+ md: 720px,
+ lg: 960px,
+ xl: 1140px,
+ xxl: 1320px
+);
+```
+
+## Best Practices
+
+### Responsive Images
+```html
+
+
+
+```
+
+### Display Property
+```html
+d-inline
+d-inline
+
+d-block
+d-block
+
+
+Hide on screens wider than lg
+Hide on screens smaller than lg
+```
+
+### Flexbox
+```html
+I'm a flexbox container!
+
+...
+...
+...
+...
+...
+
+...
+...
+...
+```
+
+### Visibility
+```html
+...
+...
+
+
+Visible on all viewport sizes
+Visible on medium and larger viewports
+Hidden on medium and larger viewports
+```
+
+## JavaScript Components
+
+### Tooltips
+```html
+
+
+
+
+```
+
+### Popovers
+```html
+
+
+
+
+```
+
+### Carousel
+```html
+
+
+
+
+
+```
+
+## Resources
+
+- [Official Documentation](https://getbootstrap.com/docs/5.3/getting-started/introduction/)
+- [Bootstrap Icons](https://icons.getbootstrap.com/)
+- [Bootstrap Examples](https://getbootstrap.com/docs/5.3/examples/)
+- [GitHub Repository](https://github.com/twbs/bootstrap)
+- [Bootstrap Blog](https://blog.getbootstrap.com/)
diff --git a/docs/ui/css-tricks.md b/docs/ui/css-tricks.md
new file mode 100644
index 0000000..4be1bf7
--- /dev/null
+++ b/docs/ui/css-tricks.md
@@ -0,0 +1,581 @@
+# CSS Tricks and Tips
+
+## Layout
+
+### Flexbox Centering
+Center elements both horizontally and vertically:
+```css
+.container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 100vh; /* Optional: for full viewport height */
+}
+```
+
+### CSS Grid Layout
+Create a responsive grid with auto-fill:
+```css
+.grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+ gap: 1rem;
+}
+```
+
+### Sticky Footer
+Keep footer at the bottom of the page:
+```css
+body {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+}
+
+main {
+ flex: 1;
+}
+```
+
+## Effects
+
+### Smooth Scrolling
+```css
+html {
+ scroll-behavior: smooth;
+}
+```
+
+### Custom Scrollbar
+```css
+/* WebKit (Chrome, Safari, newer Edge) */
+::-webkit-scrollbar {
+ width: 10px;
+}
+
+::-webkit-scrollbar-track {
+ background: #f1f1f1;
+}
+
+::-webkit-scrollbar-thumb {
+ background: #888;
+ border-radius: 5px;
+}
+
+/* Firefox */
+html {
+ scrollbar-width: thin;
+ scrollbar-color: #888 #f1f1f1;
+}
+```
+
+### Hover Effects
+```css
+.button {
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+}
+
+.button:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+```
+
+## Typography
+
+### Text Overflow Ellipsis
+```css
+.ellipsis {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 100%;
+}
+
+/* Multi-line ellipsis (3 lines) */
+.multi-line-ellipsis {
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+```
+
+### System Font Stack
+```css
+body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
+ "Helvetica Neue", Arial, sans-serif;
+}
+```
+
+## Responsive Design
+
+### Mobile-First Media Queries
+```css
+/* Base styles (mobile) */
+.container {
+ padding: 1rem;
+}
+
+/* Tablet */
+@media (min-width: 768px) {
+ .container {
+ padding: 2rem;
+ }
+}
+
+/* Desktop */
+@media (min-width: 1024px) {
+ .container {
+ max-width: 1200px;
+ margin: 0 auto;
+ }
+}
+```
+
+### Responsive Images
+```css
+.responsive-img {
+ max-width: 100%;
+ height: auto;
+ display: block;
+}
+
+/* Art direction with picture element */
+
+
+
+
+
+```
+
+## Animations
+
+### Keyframe Animation
+```css
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(20px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+.animate-fade-in {
+ animation: fadeIn 0.6s ease-out forwards;
+}
+```
+
+### Hover Underline Animation
+```css
+.hover-underline {
+ position: relative;
+ text-decoration: none;
+}
+
+.hover-underline::after {
+ content: '';
+ position: absolute;
+ width: 0;
+ height: 2px;
+ bottom: -2px;
+ left: 0;
+ background-color: currentColor;
+ transition: width 0.3s ease;
+}
+
+.hover-underline:hover::after {
+ width: 100%;
+}
+```
+
+## Forms
+
+### Custom Checkbox/Radio
+```css
+.custom-checkbox {
+ position: relative;
+ padding-left: 30px;
+ cursor: pointer;
+}
+
+.custom-checkbox input {
+ position: absolute;
+ opacity: 0;
+ cursor: pointer;
+ height: 0;
+ width: 0;
+}
+
+.checkmark {
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 20px;
+ width: 20px;
+ background-color: #eee;
+ border: 2px solid #ddd;
+ border-radius: 4px;
+}
+
+.custom-checkbox:hover input ~ .checkmark {
+ background-color: #ccc;
+}
+
+.custom-checkbox input:checked ~ .checkmark {
+ background-color: #2196F3;
+ border-color: #2196F3;
+}
+
+.checkmark:after {
+ content: "";
+ position: absolute;
+ display: none;
+}
+
+.custom-checkbox input:checked ~ .checkmark:after {
+ display: block;
+}
+
+.custom-checkbox .checkmark:after {
+ left: 6px;
+ top: 2px;
+ width: 5px;
+ height: 10px;
+ border: solid white;
+ border-width: 0 2px 2px 0;
+ transform: rotate(45deg);
+}
+```
+
+## Variables and Theming
+
+### CSS Custom Properties
+```css
+:root {
+ --primary-color: #3498db;
+ --secondary-color: #2ecc71;
+ --spacing-unit: 1rem;
+ --border-radius: 4px;
+ --transition: all 0.3s ease;
+}
+
+.button {
+ background-color: var(--primary-color);
+ padding: calc(var(--spacing-unit) * 2);
+ border-radius: var(--border-radius);
+ transition: var(--transition);
+}
+
+/* Dark mode theming */
+@media (prefers-color-scheme: dark) {
+ :root {
+ --primary-color: #2980b9;
+ --secondary-color: #27ae60;
+ }
+}
+```
+
+## Performance
+
+### Will-Change Property
+```css
+.optimize {
+ will-change: transform, opacity;
+}
+```
+
+### Content Visibility
+```css
+.long-content {
+ content-visibility: auto;
+ contain-intrinsic-size: 0 500px; /* Estimated height */
+}
+```
+
+## Browser Compatibility
+
+### Feature Queries
+```css
+@supports (display: grid) {
+ .container {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ }
+}
+
+@supports not (display: grid) {
+ .container {
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+ .container > * {
+ flex: 1 1 250px;
+ margin: 0.5rem;
+ }
+}
+```
+
+### Vendor Prefixes
+```css
+.gradient-bg {
+ background: #1e5799; /* Fallback */
+ background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 100%);
+ background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 100%);
+ background: linear-gradient(to bottom, #1e5799 0%,#2989d8 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(
+ startColorstr='#1e5799',
+ endColorstr='#2989d8',
+ GradientType=0
+ );
+}
+```
+
+## Debugging
+
+### Debugging Layout
+```css
+/* Add to any element to debug */
+.debug {
+ outline: 1px solid red;
+ background: rgba(255, 0, 0, 0.1);
+}
+
+/* Debug all elements */
+* { outline: 1px solid rgba(255, 0, 0, 0.2); }
+* * { outline: 1px solid rgba(0, 255, 0, 0.2); }
+* * * { outline: 1px solid rgba(0, 0, 255, 0.2); }
+* * * * { outline: 1px solid rgba(255, 0, 255, 0.2); }
+* * * * * { outline: 1px solid rgba(0, 255, 255, 0.2); }
+```
+
+### Print Styles
+```css
+@media print {
+ /* Hide elements when printing */
+ .no-print {
+ display: none !important;
+ }
+
+ /* Page breaks */
+ .page-break {
+ page-break-before: always;
+ }
+
+ /* Prevent text from breaking across pages */
+ p, h1, h2, h3, h4, h5, h6 {
+ page-break-inside: avoid;
+ }
+
+ /* Set page margins */
+ @page {
+ margin: 2cm;
+ }
+}
+```
+
+## Modern CSS
+
+### Aspect Ratio
+```css
+.aspect-ratio-box {
+ aspect-ratio: 16 / 9;
+ background: #f0f0f0;
+}
+```
+
+### CSS Grid Subgrid
+```css
+.grid-container {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 1rem;
+}
+
+.grid-item {
+ display: grid;
+ grid-template-rows: subgrid;
+ grid-row: span 3; /* Number of rows this item spans */
+}
+```
+
+### Container Queries
+```css
+.component {
+ container-type: inline-size;
+}
+
+@container (min-width: 400px) {
+ .component .content {
+ display: flex;
+ gap: 1rem;
+ }
+}
+```
+
+## Accessibility
+
+### Screen Reader Only
+```css
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border-width: 0;
+}
+
+/* For interactive elements that need to be visible on focus */
+.sr-only.focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ padding: 0.5em;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+ white-space: normal;
+}
+```
+
+### Reduced Motion
+```css
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
+```
+
+## Bonus: CSS Reset
+```css
+/* Box sizing rules */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+/* Remove default margin and padding */
+html,
+body,
+h1, h2, h3, h4, h5, h6,
+p, blockquote, pre,
+dl, dd, ol, ul,
+figure,
+fieldset, legend,
+textarea,
+pre, iframe,
+hr {
+ margin: 0;
+ padding: 0;
+}
+
+/* Set core body defaults */
+body {
+ min-height: 100vh;
+ scroll-behavior: smooth;
+ text-rendering: optimizeSpeed;
+ line-height: 1.5;
+}
+
+/* Remove list styles on ul, ol elements */
+ul[class],
+ol[class] {
+ list-style: none;
+}
+
+/* Make images easier to work with */
+img,
+picture,
+video,
+canvas,
+svg {
+ max-width: 100%;
+ display: block;
+}
+
+/* Inherit fonts for inputs and buttons */
+input,
+button,
+textarea,
+select {
+ font: inherit;
+}
+
+/* Remove all animations and transitions for people that prefer not to see them */
+@media (prefers-reduced-motion: reduce) {
+ * {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
+```
+
+## CSS Variables for Theming
+```css
+:root {
+ /* Colors */
+ --color-primary: #2563eb;
+ --color-secondary: #7c3aed;
+ --color-success: #10b981;
+ --color-warning: #f59e0b;
+ --color-danger: #ef4444;
+
+ /* Typography */
+ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ --font-mono: 'Fira Code', 'Courier New', monospace;
+
+ /* Spacing */
+ --space-xs: 0.25rem;
+ --space-sm: 0.5rem;
+ --space-md: 1rem;
+ --space-lg: 2rem;
+ --space-xl: 4rem;
+
+ /* Border radius */
+ --radius-sm: 0.25rem;
+ --radius-md: 0.5rem;
+ --radius-lg: 1rem;
+ --radius-full: 9999px;
+
+ /* Shadows */
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+ --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+ --shadow-md: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
+ --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
+
+ /* Transitions */
+ --transition-fast: 150ms ease;
+ --transition-normal: 300ms ease;
+ --transition-slow: 500ms ease;
+}
+
+/* Dark mode */
+@media (prefers-color-scheme: dark) {
+ :root {
+ --color-primary: #3b82f6;
+ --color-secondary: #8b5cf6;
+ --color-success: #10b981;
+ --color-warning: #f59e0b;
+ --color-danger: #ef4444;
+
+ --shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.3);
+ --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
+ --shadow-md: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2);
+ --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
+ }
+}
+```
+
+This CSS tricks guide covers a wide range of techniques from basic to advanced, including layout, animations, responsive design, accessibility, and modern CSS features. Each example is ready to use and includes comments for better understanding.
diff --git a/docs/ui/shadcn.md b/docs/ui/shadcn.md
new file mode 100644
index 0000000..8249a94
--- /dev/null
+++ b/docs/ui/shadcn.md
@@ -0,0 +1,580 @@
+# shadcn/ui Documentation
+
+## Introduction
+
+shadcn/ui is a collection of beautifully designed, accessible, and customizable React components that you can copy and paste into your apps. It's built on top of Radix UI and Tailwind CSS.
+
+## Installation
+
+### 1. Create a new Next.js project
+```bash
+npx create-next-app@latest my-app --typescript --tailwind --eslint
+cd my-app
+```
+
+### 2. Install shadcn/ui
+```bash
+npx shadcn-ui@latest init
+```
+
+### 3. Configure your `components.json`
+```json
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.js",
+ "css": "app/globals.css",
+ "baseColor": "zinc",
+ "cssVariables": true
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils"
+ }
+}
+```
+
+## Adding Components
+
+### Add a component
+```bash
+npx shadcn-ui@latest add button
+npx shadcn-ui@latest add dropdown-menu
+npx shadcn-ui@latest add card
+```
+
+### Available Components
+- `accordion`
+- `alert`
+- `alert-dialog`
+- `aspect-ratio`
+- `avatar`
+- `badge`
+- `button`
+- `calendar`
+- `card`
+- `checkbox`
+- `collapsible`
+- `command`
+- `context-menu`
+- `dialog`
+- `dropdown-menu`
+- `form`
+- `hover-card`
+- `input`
+- `label`
+- `menubar`
+- `navigation-menu`
+- `popover`
+- `progress`
+- `radio-group`
+- `scroll-area`
+- `select`
+- `separator`
+- `sheet`
+- `skeleton`
+- `slider`
+- `switch`
+- `table`
+- `tabs`
+- `textarea`
+- `toast`
+- `toaster`
+- `toggle`
+- `tooltip`
+
+## Basic Usage
+
+### Button Component
+```tsx
+import { Button } from "@/components/ui/button"
+
+export function ButtonDemo() {
+ return (
+
+ )
+}
+```
+
+### Card Component
+```tsx
+import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@/components/ui/card"
+import { Button } from "@/components/ui/button"
+
+export function CardDemo() {
+ return (
+
+
+ Create project
+ Deploy your new project in one-click.
+
+
+
+
+
+
+
+
+
+ )
+}
+```
+
+## Form Components
+
+### Form with Validation
+```tsx
+"use client"
+
+import { zodResolver } from "@hookform/resolvers/zod"
+import { useForm } from "react-hook-form"
+import * as z from "zod"
+
+import { Button } from "@/components/ui/button"
+import {
+ Form,
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form"
+import { Input } from "@/components/ui/input"
+
+const formSchema = z.object({
+ username: z.string().min(2, {
+ message: "Username must be at least 2 characters.",
+ }),
+ email: z.string().email({
+ message: "Please enter a valid email address.",
+ }),
+})
+
+export function ProfileForm() {
+ const form = useForm>({
+ resolver: zodResolver(formSchema),
+ defaultValues: {
+ username: "",
+ email: "",
+ },
+ })
+
+ function onSubmit(values: z.infer) {
+ console.log(values)
+ }
+
+ return (
+
+
+ )
+}
+```
+
+## Dark Mode
+
+### Theme Provider
+```tsx
+// app/providers.tsx
+"use client"
+
+import * as React from "react"
+import { ThemeProvider as NextThemesProvider } from "next-themes"
+import { type ThemeProviderProps } from "next-themes/dist/types"
+
+export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
+ return {children}
+}
+
+// app/layout.tsx
+import { ThemeProvider } from "@/app/providers"
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+
+
+ {children}
+
+
+
+ )
+}
+
+// components/theme-toggle.tsx
+"use client"
+
+import { Moon, Sun } from "lucide-react"
+import { useTheme } from "next-themes"
+
+import { Button } from "@/components/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+
+export function ModeToggle() {
+ const { setTheme } = useTheme()
+
+ return (
+
+
+
+
+
+ setTheme("light")}>
+ Light
+
+ setTheme("dark")}>
+ Dark
+
+ setTheme("system")}>
+ System
+
+
+
+ )
+}
+```
+
+## Customization
+
+### Customizing Theme
+```ts
+// tailwind.config.js
+const { fontFamily } = require('tailwindcss/defaultTheme')
+
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ darkMode: ["class"],
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ },
+ borderRadius: {
+ lg: `var(--radius)`,
+ md: `calc(var(--radius) - 2px)`,
+ sm: "calc(var(--radius) - 4px)",
+ },
+ fontFamily: {
+ sans: ["var(--font-sans)", ...fontFamily.sans],
+ },
+ keyframes: {
+ "accordion-down": {
+ from: { height: 0 },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: 0 },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+}
+```
+
+## Advanced Usage
+
+### Custom Component with Variants
+```tsx
+import { cva, type VariantProps } from "class-variance-authority"
+import { Loader2 } from "lucide-react"
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "underline-offset-4 hover:underline text-primary",
+ },
+ size: {
+ default: "h-10 py-2 px-4",
+ sm: "h-9 px-3 rounded-md",
+ lg: "h-11 px-8 rounded-md",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ isLoading?: boolean
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, isLoading, children, ...props }, ref) => {
+ return (
+
+ )
+ }
+)
+Button.displayName = "Button"
+
+export { Button, buttonVariants }
+```
+
+## Best Practices
+
+1. **Component Composition**
+ - Compose smaller components to build complex UIs
+ - Use the `asChild` prop for flexible component composition
+
+2. **Performance**
+ - Use dynamic imports for large components
+ - Implement proper loading states
+ - Use `React.memo` for expensive components
+
+3. **Accessibility**
+ - All components are built with accessibility in mind
+ - Use proper ARIA attributes
+ - Ensure keyboard navigation works
+
+4. **Theming**
+ - Use CSS variables for theming
+ - Support both light and dark modes
+ - Provide proper contrast ratios
+
+## Common Patterns
+
+### Data Table with Sorting
+```tsx
+"use client"
+
+import {
+ ColumnDef,
+ ColumnFiltersState,
+ SortingState,
+ VisibilityState,
+ flexRender,
+ getCoreRowModel,
+ getFilteredRowModel,
+ getPaginationRowModel,
+ getSortedRowModel,
+ useReactTable,
+} from "@tanstack/react-table"
+
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table"
+
+interface DataTableProps {
+ columns: ColumnDef[]
+ data: TData[]
+}
+
+export function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const [sorting, setSorting] = React.useState([])
+ const [columnFilters, setColumnFilters] = React.useState([])
+ const [columnVisibility, setColumnVisibility] = React.useState({})
+ const [rowSelection, setRowSelection] = React.useState({})
+
+ const table = useReactTable({
+ data,
+ columns,
+ state: {
+ sorting,
+ columnFilters,
+ columnVisibility,
+ rowSelection,
+ },
+ onSortingChange: setSorting,
+ onColumnFiltersChange: setColumnFilters,
+ onColumnVisibilityChange: setColumnVisibility,
+ onRowSelectionChange: setRowSelection,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: getPaginationRowModel(),
+ getSortedRowModel: getSortedRowModel(),
+ getFilteredRowModel: getFilteredRowModel(),
+ })
+
+ return (
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => {
+ return (
+
+ {header.isPlaceholder
+ ? null
+ : flexRender(
+ header.column.columnDef.header,
+ header.getContext()
+ )}
+
+ )
+ })}
+
+ ))}
+
+
+ {table.getRowModel().rows?.length ? (
+ table.getRowModel().rows.map((row) => (
+
+ {row.getVisibleCells().map((cell) => (
+
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+
+ ))}
+
+ ))
+ ) : (
+
+
+ No results.
+
+
+ )}
+
+
+
+ )
+}
+```
+
+## Resources
+
+- [Official Documentation](https://ui.shadcn.com/)
+- [GitHub Repository](https://github.com/shadcn/ui)
+- [Radix UI Primitives](https://www.radix-ui.com/)
+- [Tailwind CSS](https://tailwindcss.com/)
+- [Class Variance Authority](https://github.com/joe-bell/cva)
diff --git a/docs/vue/components.md b/docs/vue/components.md
new file mode 100644
index 0000000..823b11c
--- /dev/null
+++ b/docs/vue/components.md
@@ -0,0 +1,1468 @@
+# Vue Components
+
+## Table of Contents
+1. [Component Basics](#component-basics)
+2. [Component Registration](#component-registration)
+3. [Props](#props)
+4. [Emits](#emits)
+5. [Slots](#slots)
+6. [Provide/Inject](#provide--inject)
+7. [Dynamic Components](#dynamic-components)
+8. [Async Components](#async-components)
+9. [Composables](#composables)
+10. [Render Functions & JSX](#render-functions--jsx)
+11. [Custom Directives](#custom-directives)
+12. [Plugins](#plugins)
+13. [Performance Optimization](#performance-optimization)
+
+## Component Basics
+
+### Single File Components (SFC)
+```vue
+
+
+
{{ msg }}
+
+
+
+
+
+
+
+```
+
+### Options API (Legacy)
+```vue
+
+
+
{{ msg }}
+
+
+
+
+
+
+
+```
+
+## Component Registration
+
+### Global Registration
+```javascript
+// main.js
+import { createApp } from 'vue'
+import App from './App.vue'
+import MyComponent from './components/MyComponent.vue'
+
+const app = createApp(App)
+
+// Register globally
+app.component('MyComponent', MyComponent)
+
+app.mount('#app')
+```
+
+### Local Registration
+```vue
+
+
+
+
+
+```
+
+### Auto-import Components
+```javascript
+// plugins/components.js
+import { defineAsyncComponent } from 'vue'
+
+export default {
+ install(app) {
+ const components = import.meta.glob('./components/**/*.vue')
+
+ for (const [path, component] of Object.entries(components)) {
+ const componentName = path
+ .split('/')
+ .pop()
+ .replace(/\.\w+$/, '')
+
+ app.component(componentName, defineAsyncComponent(component))
+ }
+ }
+}
+
+// main.js
+import { createApp } from 'vue'
+import App from './App.vue'
+import components from './plugins/components'
+
+const app = createApp(App)
+app.use(components)
+app.mount('#app')
+```
+
+## Props
+
+### Prop Types and Validation
+```vue
+
+```
+
+### One-Way Data Flow
+```vue
+
+
+
+
+
+```
+
+## Emits
+
+### Declaring Emits
+```vue
+
+```
+
+### v-model with Components
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Multiple v-model Bindings
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## Slots
+
+### Basic Slots
+```vue
+
+
+
+
+
+ Default content
+
+
+
+
+
+
+
+
+ My App
+
+
+ Main content goes here
+
+
+ Copyright 2023
+
+
+```
+
+### Scoped Slots
+```vue
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }}. {{ item.text }}
+
+
+
+```
+
+### Renderless Components
+```vue
+
+
+
+
+
+
+
+
+
+ Mouse is at: {{ x }}, {{ y }}
+
+```
+
+## Provide / Inject
+
+### Basic Usage
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### With Symbol Keys
+```javascript
+// keys.js
+export const COUNT_KEY = Symbol('count')
+export const INCREMENT_KEY = Symbol('increment')
+
+// ParentComponent.vue
+import { provide } from 'vue'
+import { COUNT_KEY, INCREMENT_KEY } from './keys'
+
+const count = ref(0)
+provide(COUNT_KEY, count)
+provide(INCREMENT_KEY, () => count.value++)
+
+// ChildComponent.vue
+import { inject } from 'vue'
+import { COUNT_KEY, INCREMENT_KEY } from './keys'
+
+const count = inject(COUNT_KEY, 0)
+const increment = inject(INCREMENT_KEY)
+```
+
+## Dynamic Components
+
+### Basic Dynamic Components
+```vue
+
+
+
+
+
+
+```
+
+### Keep-Alive Components
+```vue
+
+
+
+
+
+
+
+
+
+
+```
+
+## Async Components
+
+### Basic Async Component
+```javascript
+// AsyncComponent.vue
+import { defineAsyncComponent } from 'vue'
+
+export default {
+ components: {
+ // Simple usage
+ AdminPanel: defineAsyncComponent(() =>
+ import('./AdminPanel.vue')
+ ),
+
+ // With options
+ UserProfile: defineAsyncComponent({
+ // The loader function
+ loader: () => import('./UserProfile.vue'),
+
+ // A component to use while the async component is loading
+ loadingComponent: LoadingComponent,
+
+ // A component to use if the load fails
+ errorComponent: ErrorComponent,
+
+ // Delay before showing the loading component. Default: 200ms
+ delay: 200,
+
+ // The error component will be displayed if a timeout is
+ // provided and exceeded. Default: Infinity
+ timeout: 3000,
+
+ // A function that returns a boolean indicating whether the async component should retry when the loader promise rejects
+ onError(error, retry, fail, attempts) {
+ if (error.message.match(/fetch/) && attempts <= 3) {
+ // Retry on fetch errors, 3 max attempts
+ retry()
+ } else {
+ // Note that retry/fail are like resolve/reject of a promise:
+ // one of them must be called for the error handling to continue.
+ fail()
+ }
+ }
+ })
+ }
+}
+```
+
+### Suspense (Experimental)
+```vue
+
+
+
+
+
+
+
+ Loading...
+
+
+
+
+
+```
+
+## Composables
+
+### Creating a Composable
+```javascript
+// useMouse.js
+import { ref, onMounted, onUnmounted } from 'vue'
+
+export function useMouse() {
+ const x = ref(0)
+ const y = ref(0)
+
+ function update(event) {
+ x.value = event.pageX
+ y.value = event.pageY
+ }
+
+ onMounted(() => window.addEventListener('mousemove', update))
+ onUnmounted(() => window.removeEventListener('mousemove', update))
+
+ return { x, y }
+}
+
+// Usage in component
+import { useMouse } from './useMouse'
+
+const { x, y } = useMouse()
+```
+
+### Async Composable
+```javascript
+// useFetch.js
+import { ref, isRef, unref, watchEffect } from 'vue'
+
+export function useFetch(url) {
+ const data = ref(null)
+ const error = ref(null)
+ const isPending = ref(false)
+
+ async function doFetch() {
+ // Reset state
+ data.value = null
+ error.value = null
+ isPending.value = true
+
+ try {
+ // Unwrap the url in case it's a ref
+ const urlValue = unref(url)
+ const response = await fetch(urlValue)
+ data.value = await response.json()
+ } catch (e) {
+ error.value = e
+ } finally {
+ isPending.value = false
+ }
+ }
+
+ if (isRef(url)) {
+ // Setup reactive re-fetch if input URL is a ref
+ watchEffect(doFetch)
+ } else {
+ // Otherwise, just fetch once
+ doFetch()
+ }
+
+ return { data, error, isPending, retry: doFetch }
+}
+
+// Usage
+const { data, isPending, error } = useFetch('https://api.example.com/data')
+// Or with a ref
+const url = ref('https://api.example.com/data')
+const { data } = useFetch(url)
+```
+
+## Render Functions & JSX
+
+### Basic Render Function
+```javascript
+// MyComponent.js
+import { h } from 'vue'
+
+export default {
+ props: ['level'],
+ render() {
+ return h(
+ 'h' + this.level, // tag name
+ {}, // props/attributes
+ this.$slots.default() // array of children
+ )
+ }
+}
+
+// With JSX
+import { defineComponent } from 'vue'
+
+export default defineComponent({
+ props: ['level'],
+ setup(props, { slots }) {
+ return () => (
+
+ {slots.default?.()}
+
+ )
+ }
+})
+```
+
+### Functional Components
+```javascript
+// FunctionalComponent.js
+import { h } from 'vue'
+
+const FunctionalComponent = (props, { slots, emit, attrs }) => {
+ return h('div', { class: 'functional' }, [
+ h('button', { onClick: () => emit('click') }, 'Click me'),
+ slots.default?.()
+ ])
+}
+
+FunctionalComponent.props = ['title']
+FunctionalComponent.emits = ['click']
+
+export default FunctionalComponent
+```
+
+## Custom Directives
+
+### Basic Directive
+```javascript
+// v-focus directive
+const vFocus = {
+ mounted(el) {
+ el.focus()
+ }
+}
+
+// Usage in template
+//
+
+// Global registration
+app.directive('focus', {
+ mounted(el) {
+ el.focus()
+ }
+})
+```
+
+### Directive with Arguments and Modifiers
+```javascript
+const vPin = {
+ mounted(el, binding) {
+ el.style.position = 'fixed'
+
+ // Binding value
+ const s = binding.arg || 'top'
+ el.style[s] = binding.value + 'px'
+
+ // Modifiers
+ if (binding.modifiers.animate) {
+ el.style.transition = 'all 0.3s'
+ }
+ },
+
+ // Updated when the bound value changes
+ updated(el, binding) {
+ const s = binding.arg || 'top'
+ el.style[s] = binding.value + 'px'
+ }
+}
+
+// Usage
+// Pinned element
+```
+
+## Plugins
+
+### Creating a Plugin
+```javascript
+// plugins/i18n.js
+export default {
+ install: (app, options) => {
+ // Add a global method
+ app.config.globalProperties.$translate = (key) => {
+ return key.split('.').reduce((o, i) => {
+ if (o) return o[i]
+ }, options.messages)
+ }
+
+ // Provide a value to the app
+ app.provide('i18n', options)
+
+ // Add a custom directive
+ app.directive('my-directive', {
+ mounted(el, binding, vnode, prevVnode) {
+ // ...
+ }
+ })
+
+ // Add a global mixin
+ app.mixin({
+ created() {
+ // ...
+ }
+ })
+ }
+}
+
+// main.js
+import { createApp } from 'vue'
+import App from './App.vue'
+import i18nPlugin from './plugins/i18n'
+
+const app = createApp(App)
+
+app.use(i18nPlugin, {
+ messages: {
+ welcome: 'Welcome',
+ buttons: {
+ save: 'Save',
+ cancel: 'Cancel'
+ }
+ }
+})
+
+app.mount('#app')
+```
+
+## Performance Optimization
+
+### v-once
+```vue
+
+
+ {{ heavyComputation() }}
+
+
+
+
+```
+
+### v-memo
+```vue
+
+
+
+
ID: {{ item.id }} - selected: {{ item.id === selected }}
+
...more child nodes
+
+
+```
+
+### Virtual Scrolling
+```vue
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+```
+
+### Lazy Loading Routes
+```javascript
+// router.js
+import { createRouter, createWebHistory } from 'vue-router'
+
+const routes = [
+ {
+ path: '/',
+ component: () => import('./views/Home.vue')
+ },
+ {
+ path: '/about',
+ // Route level code-splitting
+ component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
+ },
+ {
+ path: '/admin',
+ // Lazy load admin routes
+ component: () => import('./views/AdminLayout.vue'),
+ children: [
+ {
+ path: 'dashboard',
+ component: () => import('./views/admin/Dashboard.vue')
+ },
+ // ...
+ ]
+ }
+]
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes
+})
+
+export default router
+```
+
+### Optimizing Updates
+```vue
+
+
+
+
+
+
+
+
+
+ Toggled content
+
+
+
+```
+
+## Component Design Patterns
+
+### Compound Components
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Content for Tab 1
+
+
+ Content for Tab 2
+
+
+```
+
+### Renderless Components
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+ Hover over me!
+
+
+```
+
+### Controlled Components
+```vue
+
+
+
+
+
+
+
+
+```
+
+## Testing Components
+
+### Unit Testing with Vitest
+```javascript
+// Component.spec.js
+import { mount } from '@vue/test-utils'
+import Component from './Component.vue'
+
+describe('Component', () => {
+ it('renders correctly', () => {
+ const wrapper = mount(Component, {
+ props: {
+ msg: 'Hello, World!'
+ },
+ global: {
+ stubs: ['FontAwesomeIcon']
+ }
+ })
+
+ expect(wrapper.text()).toContain('Hello, World!')
+ })
+
+ it('emits an event when clicked', async () => {
+ const wrapper = mount(Component)
+ await wrapper.find('button').trigger('click')
+ expect(wrapper.emitted('click')).toHaveLength(1)
+ })
+})
+```
+
+### Component Testing with Testing Library
+```javascript
+import { render, screen, fireEvent } from '@testing-library/vue'
+import userEvent from '@testing-library/user-event'
+import Component from './Component.vue'
+
+test('renders a greeting', () => {
+ render(Component, {
+ props: {
+ msg: 'Hello, World!'
+ }
+ })
+
+ expect(screen.getByText('Hello, World!')).toBeInTheDocument()
+})
+
+test('increments counter on button click', async () => {
+ render(Component)
+ const button = screen.getByRole('button', { name: /count/i })
+
+ await userEvent.click(button)
+
+ expect(button).toHaveTextContent('Count: 1')
+})
+```
+
+## Accessibility (a11y)
+
+### ARIA Attributes
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+### Focus Management
+```vue
+
+
+
+
+
+
Dialog Title
+
Dialog content goes here.
+
+
+
+
+
+
+```
+
+## Internationalization (i18n)
+
+### Using vue-i18n
+```javascript
+// plugins/i18n.js
+import { createI18n } from 'vue-i18n'
+
+const messages = {
+ en: {
+ message: {
+ hello: 'Hello!',
+ welcome: 'Welcome, {name}!'
+ }
+ },
+ es: {
+ message: {
+ hello: '¡Hola!',
+ welcome: '¡Bienvenido, {name}!'
+ }
+ }
+}
+
+const i18n = createI18n({
+ locale: 'en',
+ fallbackLocale: 'en',
+ messages
+})
+
+export default i18n
+
+// main.js
+import { createApp } from 'vue'
+import App from './App.vue'
+import i18n from './plugins/i18n'
+
+const app = createApp(App)
+app.use(i18n)
+app.mount('#app')
+
+// Usage in components
+
+
+
{{ $t('message.hello') }}
+
{{ $t('message.welcome', { name: 'John' }) }}
+
+
+
+
+
+```
+
+## Server-Side Rendering (SSR)
+
+### Basic SSR with Vite
+```javascript
+// server.js
+import { createSSRApp } from 'vue'
+import { renderToString } from 'vue/server-renderer'
+import App from './src/App.vue'
+
+export async function render(url) {
+ const app = createSSRApp(App)
+
+ const appHtml = await renderToString(app)
+
+ return `
+
+
+
+ Vue SSR
+
+
+ ${appHtml}
+
+
+
+ `
+}
+
+// entry-client.js
+import { createApp } from 'vue'
+import App from './App.vue'
+
+const app = createApp(App)
+app.mount('#app')
+
+// entry-server.js
+import { createSSRApp } from 'vue'
+import App from './App.vue'
+
+export default function () {
+ const app = createSSRApp(App)
+
+ return {
+ app
+ }
+}
+```
+
+## Progressive Web App (PWA)
+
+### Using Vite PWA Plugin
+```bash
+npm install -D vite-plugin-pwa
+```
+
+```javascript
+// vite.config.js
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import { VitePWA } from 'vite-plugin-pwa'
+
+export default defineConfig({
+ plugins: [
+ vue(),
+ VitePWA({
+ registerType: 'autoUpdate',
+ includeAssets: ['favicon.ico', 'robots.txt', 'apple-touch-icon.png'],
+ manifest: {
+ name: 'My Awesome App',
+ short_name: 'MyApp',
+ description: 'My Awesome App description',
+ theme_color: '#ffffff',
+ icons: [
+ {
+ src: 'pwa-192x192.png',
+ sizes: '192x192',
+ type: 'image/png'
+ },
+ {
+ src: 'pwa-512x512.png',
+ sizes: '512x512',
+ type: 'image/png'
+ }
+ ]
+ }
+ })
+ ]
+})
+
+// Register service worker in main.js
+if ('serviceWorker' in navigator) {
+ window.addEventListener('load', () => {
+ navigator.serviceWorker.register('/sw.js')
+ })
+}
+```
+
+## Migration from Vue 2
+
+### Migration Build
+```javascript
+// vue.config.js
+module.exports = {
+ configureWebpack: {
+ resolve: {
+ alias: {
+ vue: '@vue/compat',
+ 'vue-router': 'vue-router/dist/vue-router.compat.js'
+ }
+ },
+ module: {
+ rules: [
+ {
+ test: /\.vue$/,
+ loader: 'vue-loader',
+ options: {
+ compilerOptions: {
+ compatConfig: {
+ MODE: 2 // or 3 for Vue 3 mode with some Vue 2 compat
+ }
+ }
+ }
+ }
+ ]
+ }
+ }
+}
+```
+
+### Breaking Changes
+1. **Global API**: `Vue` is no longer a constructor, use `createApp`
+2. **Template Directives**: `v-model` syntax changed, `v-for` key usage changed
+3. **Events API**: `$on`, `$off`, and `$once` removed
+4. **Filters** removed, use methods or computed properties
+5. **Functional Components** now need to be plain functions
+6. **Async Components** now use `defineAsyncComponent`
+7. **Render Function** API changed
+8. **Custom Directives** lifecycle hooks renamed
+9. **Transition** classes changed
+10. **v-model** in components now uses `modelValue` and `update:modelValue`
+
+## Resources
+
+### Official Documentation
+- [Vue 3 Documentation](https://v3.vuejs.org/)
+- [Composition API](https://v3.vuejs.org/guide/composition-api-introduction.html)
+- [Single File Components](https://v3.vuejs.org/guide/single-file-component.html)
+- [Vue Router](https://next.router.vuejs.org/)
+- [Pinia](https://pinia.vuejs.org/)
+- [VueUse](https://vueuse.org/)
+
+### Tools
+- [Vue DevTools](https://devtools.vuejs.org/)
+- [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)
+- [Vitest](https://vitest.dev/)
+- [Vue Test Utils](https://next.vue-test-utils.vuejs.org/)
+- [VueUse](https://vueuse.org/)
+
+### UI Frameworks
+- [Vuetify](https://next.vuetifyjs.com/)
+- [Quasar](https://quasar.dev/)
+- [Element Plus](https://element-plus.org/)
+- [Naive UI](https://www.naiveui.com/)
+- [PrimeVue](https://primefaces.org/primevue/)
+
+### Learning Resources
+- [Vue Mastery](https://www.vuemastery.com/)
+- [Vue School](https://vueschool.io/)
+- [Vue.js Developers](https://vuejsdevelopers.com/)
+- [VueDose](https://vuedose.tips/)
diff --git a/docs/vue/reactivity.md b/docs/vue/reactivity.md
new file mode 100644
index 0000000..3c63034
--- /dev/null
+++ b/docs/vue/reactivity.md
@@ -0,0 +1,533 @@
+# Vue Reactivity System
+
+## Table of Contents
+1. [Introduction to Reactivity](#introduction-to-reactivity)
+2. [Reactive State](#reactive-state)
+3. [Reactive Objects](#reactive-objects)
+4. [Reactive Arrays](#reactive-arrays)
+5. [Reactive Refs](#reactive-refs)
+6. [Computed Properties](#computed-properties)
+7. [Watching Reactive Data](#watching-reactive-data)
+8. [Effect Scope](#effect-scope)
+9. [Reactivity Utilities](#reactivity-utilities)
+10. [Performance Considerations](#performance-considerations)
+
+## Introduction to Reactivity
+
+Vue's reactivity system is the foundation of its component model. When you change data, the view updates automatically.
+
+### How Reactivity Works
+1. **Proxy-based** (Vue 3): Uses JavaScript Proxies to track property access
+2. **Getter/Setter** (Vue 2): Uses Object.defineProperty for reactivity
+
+## Reactive State
+
+### `reactive()`
+Creates a reactive object (works with objects, arrays, Map, Set).
+
+```typescript
+import { reactive } from 'vue'
+
+const state = reactive({
+ count: 0,
+ user: {
+ name: 'John',
+ age: 30
+ },
+ todos: []
+})
+
+// Nested objects are reactive
+state.user.name = 'Jane' // triggers reactivity
+```
+
+### `ref()`
+Creates a reactive reference to a value.
+
+```typescript
+import { ref } from 'vue'
+
+const count = ref(0) // { value: 0 }
+const user = ref({
+ name: 'John',
+ age: 30
+})
+
+// Access with .value
+count.value++ // triggers reactivity
+user.value.name = 'Jane' // also reactive
+
+// In templates, no .value needed
+// {{ count }}
+```
+
+### `readonly()`
+Creates a read-only proxy of the original object.
+
+```typescript
+import { reactive, readonly } from 'vue'
+
+const original = reactive({ count: 0 })
+const copy = readonly(original)
+
+// Mutating original will trigger updates in copy
+original.count++ // works
+copy.count++ // warning: cannot mutate readonly property
+```
+
+## Reactive Objects
+
+### Shallow Reactive
+Only the top-level properties are reactive.
+
+```typescript
+import { shallowReactive } from 'vue'
+
+const state = shallowReactive({
+ count: 0,
+ user: { name: 'John' } // nested object is NOT reactive
+})
+
+state.count++ // reactive
+state.user.name = 'Jane' // NOT reactive
+```
+
+### Reactive vs Ref
+
+| Feature | `reactive` | `ref` |
+|-------------------|------------|-------|
+| Works with | Objects/Arrays | Any value |
+| Access in JS | Direct | `.value` |
+| Template usage | Direct | Unwraps automatically |
+| TypeScript support | Good | Excellent |
+| Watch deep by default | Yes | No |
+
+## Reactive Arrays
+
+### Array Reactivity
+```typescript
+const list = reactive([1, 2, 3])
+
+// These methods trigger updates
+list.push(4)
+list.pop()
+list.splice(0, 1, 5)
+list.sort()
+list.reverse()
+
+// Replacing the entire array works
+list = [...list, 4] // with let
+list.splice(0, list.length, ...newList) // with const
+```
+
+### Caveats with Arrays
+```typescript
+// These won't trigger updates
+list[0] = 5 // Won't work
+list.length = 0 // Won't work
+
+// Solutions
+list.splice(0, 1, 5) // Use array methods
+list.splice(0) // Clear array
+```
+
+## Computed Properties
+
+### Basic Usage
+```typescript
+import { ref, computed } from 'vue'
+
+const count = ref(0)
+const double = computed(() => count.value * 2)
+
+console.log(double.value) // 0
+count.value++
+console.log(double.value) // 2
+```
+
+### Writable Computed
+```typescript
+const firstName = ref('John')
+const lastName = ref('Doe')
+
+const fullName = computed({
+ get() {
+ return `${firstName.value} ${lastName.value}`
+ },
+ set(newValue) {
+ [firstName.value, lastName.value] = newValue.split(' ')
+ }
+})
+
+fullName.value = 'Jane Smith' // Updates firstName and lastName
+```
+
+## Watching Reactive Data
+
+### `watch`
+```typescript
+import { ref, watch } from 'vue'
+
+const count = ref(0)
+const user = reactive({ name: 'John' })
+
+// Watch a single ref
+watch(count, (newValue, oldValue) => {
+ console.log(`Count changed from ${oldValue} to ${newValue}`)
+})
+
+// Watch a getter function
+watch(
+ () => user.name,
+ (newName, oldName) => {
+ console.log(`Name changed from ${oldName} to ${newName}`)
+ }
+)
+
+// Watch multiple sources
+watch(
+ [() => user.name, count],
+ ([newName, newCount], [oldName, oldCount]) => {
+ console.log('Name or count changed')
+ }
+)
+```
+
+### `watchEffect`
+Runs immediately and tracks reactive dependencies automatically.
+
+```typescript
+import { ref, watchEffect } from 'vue'
+
+const count = ref(0)
+const double = ref(0)
+
+watchEffect(() => {
+ // Automatically tracks count
+ double.value = count.value * 2
+})
+
+count.value++ // Triggers effect
+```
+
+### Watch Options
+```typescript
+watch(
+ source,
+ callback,
+ {
+ immediate: true, // Run immediately
+ deep: true, // Deep watch
+ flush: 'post', // Run after DOM updates
+ onTrack(e) { // Debugging
+ debugger
+ },
+ onTrigger(e) { // Debugging
+ debugger
+ }
+ }
+)
+```
+
+## Effect Scope
+
+### `effectScope`
+Groups multiple effects together for better organization and cleanup.
+
+```typescript
+import { effectScope, ref, watch, watchEffect } from 'vue'
+
+const scope = effectScope()
+
+scope.run(() => {
+ const count = ref(0)
+
+ watch(count, () => console.log('Count changed'))
+ watchEffect(() => console.log('Effect:', count.value))
+
+ // All effects are stopped when scope is stopped
+ setTimeout(() => scope.stop(), 1000)
+})
+```
+
+## Reactivity Utilities
+
+### `toRef` and `toRefs`
+```typescript
+import { reactive, toRef, toRefs } from 'vue'
+
+const state = reactive({
+ foo: 1,
+ bar: 2
+})
+
+// Convert a single property to a ref
+const fooRef = toRef(state, 'foo')
+
+// Convert all properties to refs
+const { foo, bar } = toRefs(state)
+
+// Now you can pass refs around without losing reactivity
+function useFeatureX(foo, bar) {
+ // Both are refs that stay synced with the original
+ return {
+ foo,
+ bar,
+ sum: computed(() => foo.value + bar.value)
+ }
+}
+```
+
+### `isReactive` and `isRef`
+```typescript
+import { isReactive, isRef, reactive, ref } from 'vue'
+
+console.log(isReactive(reactive({}))) // true
+console.log(isRef(ref(0))) // true
+```
+
+### `shallowRef` and `triggerRef`
+```typescript
+import { shallowRef, triggerRef } from 'vue'
+
+const state = shallowRef({ count: 0 })
+
+// Doesn't trigger updates for nested properties
+state.value.count++ // No update
+
+// Force update
+triggerRef(state) // Triggers update
+```
+
+## Performance Considerations
+
+1. **Avoid Large Reactive Objects**
+ - Keep reactive state minimal
+ - Use `shallowRef` or `shallowReactive` for large objects
+
+2. **Debounce Expensive Operations**
+ ```typescript
+ import { debounce } from 'lodash-es'
+
+ const searchQuery = ref('')
+ const searchResults = ref([])
+
+ const search = debounce(async () => {
+ searchResults.value = await fetchResults(searchQuery.value)
+ }, 500)
+
+ watch(searchQuery, search)
+ ```
+
+3. **Use `computed` for Derived State**
+ - Caches results until dependencies change
+ - More efficient than methods in templates
+
+4. **Batch Updates**
+ ```typescript
+ import { nextTick } from 'vue'
+
+ // Multiple state updates in the same tick
+ const update = () => {
+ state.a = 1
+ state.b = 2
+ // DOM updates once after this function
+ }
+
+ // Or use nextTick
+ const update = async () => {
+ state.a = 1
+ await nextTick()
+ // DOM is updated
+ state.b = 2
+ }
+ ```
+
+5. **Virtual Scrolling for Large Lists**
+ ```vue
+
+
+
+
+
+
+
+ ```
+
+## Common Pitfalls
+
+1. **Destructuring Reactive Objects**
+ ```typescript
+ // ❌ Loses reactivity
+ const { x, y } = reactive({ x: 0, y: 0 })
+
+ // ✅ Use toRefs
+ const pos = reactive({ x: 0, y: 0 })
+ const { x, y } = toRefs(pos)
+ ```
+
+2. **Async Updates**
+ ```typescript
+ // ❌ May miss updates
+ const update = async () => {
+ state.data = await fetchData()
+ // DOM not updated yet
+ doSomethingWithDOM()
+ }
+
+ // ✅ Use nextTick
+ const update = async () => {
+ state.data = await fetchData()
+ await nextTick()
+ // DOM is updated
+ doSomethingWithDOM()
+ }
+ ```
+
+3. **Circular References**
+ ```typescript
+ // ❌ Creates infinite loop
+ const obj = reactive({})
+ obj.self = obj // Circular reference
+
+ // ✅ Break the cycle
+ const obj = reactive({
+ self: null as any
+ })
+ obj.self = obj // Still reactive, but no infinite loop
+ ```
+
+## Advanced Reactivity Patterns
+
+### Custom Ref
+```typescript
+import { customRef } from 'vue'
+
+function useDebouncedRef(value, delay = 200) {
+ let timeout
+ return customRef((track, trigger) => {
+ return {
+ get() {
+ track()
+ return value
+ },
+ set(newValue) {
+ clearTimeout(timeout)
+ timeout = setTimeout(() => {
+ value = newValue
+ trigger()
+ }, delay)
+ }
+ }
+ })
+}
+
+// Usage
+const text = useDebouncedRef('hello')
+```
+
+### Reactive State Machine
+```typescript
+import { reactive } from 'vue'
+
+function createMachine(config) {
+ const state = reactive({
+ current: config.initial,
+ transition(event) {
+ const currentState = config.states[state.current]
+ const nextState = currentState?.on?.[event]
+
+ if (nextState) {
+ currentState.onExit?.()
+ state.current = nextState
+ config.states[nextState].onEnter?.()
+ return true
+ }
+ return false
+ }
+ })
+
+ return state
+}
+
+// Usage
+const trafficLight = createMachine({
+ initial: 'red',
+ states: {
+ red: {
+ on: { next: 'green' },
+ onEnter: () => console.log('Stop!')
+ },
+ yellow: {
+ on: { next: 'red' },
+ onEnter: () => console.log('Slow down!')
+ },
+ green: {
+ on: { next: 'yellow' },
+ onEnter: () => console.log('Go!')
+ }
+ }
+})
+
+trafficLight.transition('next') // Logs: "Go!"
+```
diff --git a/docs/vue/routing.md b/docs/vue/routing.md
new file mode 100644
index 0000000..f585ada
--- /dev/null
+++ b/docs/vue/routing.md
@@ -0,0 +1,1084 @@
+# Vue Router: Official Router for Vue.js
+
+## Table of Contents
+- [Introduction to Vue Router](#introduction-to-vue-router)
+- [Installation & Setup](#installation--setup)
+- [Basic Routing](#basic-routing)
+- [Dynamic Route Matching](#dynamic-route-matching)
+- [Nested Routes](#nested-routes)
+- [Programmatic Navigation](#programmatic-navigation)
+- [Named Routes & Views](#named-routes--views)
+- [Route Parameters & Props](#route-parameters--props)
+- [Navigation Guards](#navigation-guards)
+- [Route Meta Fields](#route-meta-fields)
+- [Transitions](#transitions)
+- [Data Fetching](#data-fetching)
+- [Scroll Behavior](#scroll-behavior)
+- [Lazy Loading Routes](#lazy-loading-routes)
+- [Navigation Failures](#navigation-failures)
+- [Composition API](#composition-api)
+- [TypeScript Support](#typescript-support)
+- [Authentication & Protected Routes](#authentication--protected-routes)
+- [Error Handling](#error-handling)
+- [Performance Optimization](#performance-optimization)
+- [Deployment](#deployment)
+- [Common Patterns](#common-patterns)
+- [Migration from Vue 2](#migration-from-vue-2)
+
+## Introduction to Vue Router
+
+Vue Router is the official router for Vue.js. It deeply integrates with Vue.js core to make building Single Page Applications with Vue.js a breeze.
+
+### Key Features
+- Nested route/view mapping
+- Modular, component-based router configuration
+- Route params, query, wildcards
+- View transition effects
+- Fine-grained navigation control
+- Links with automatic active CSS classes
+- HTML5 history or hash mode, with auto-fallback in IE9
+- Customizable scroll behavior
+- Proper encoding for URLs
+- Route level code-splitting
+
+## Installation & Setup
+
+### Installation
+
+```bash
+# For Vue 3
+npm install vue-router@4
+# or with yarn
+yarn add vue-router@4
+```
+
+### Basic Setup
+
+```javascript
+// router/index.js
+import { createRouter, createWebHistory } from 'vue-router'
+import Home from '../views/Home.vue'
+
+const routes = [
+ {
+ path: '/',
+ name: 'Home',
+ component: Home
+ },
+ {
+ path: '/about',
+ name: 'About',
+ component: () => import('../views/About.vue')
+ }
+]
+
+const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes
+})
+
+export default router
+```
+
+```javascript
+// main.js
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+
+const app = createApp(App)
+app.use(router)
+app.mount('#app')
+```
+
+### Router View
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Basic Routing
+
+### Route Configuration
+
+```javascript
+const routes = [
+ { path: '/', component: Home },
+ { path: '/about', component: About },
+ { path: '/contact', component: Contact }
+]
+```
+
+### HTML5 History Mode
+
+```javascript
+import { createRouter, createWebHistory } from 'vue-router'
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes
+})
+```
+
+### Hash Mode
+
+```javascript
+import { createRouter, createWebHashHistory } from 'vue-router'
+
+const router = createRouter({
+ history: createWebHashHistory(),
+ routes
+})
+```
+
+## Dynamic Route Matching
+
+### Dynamic Segments
+
+```javascript
+const routes = [
+ // Dynamic segment starts with a colon
+ { path: '/users/:id', component: User },
+
+ // Multiple dynamic segments
+ { path: '/users/:username/posts/:postId', component: UserPost }
+]
+```
+
+### Accessing Route Parameters
+
+```vue
+
+
+
User {{ $route.params.id }}
+
+
+
+
+```
+
+### Catch All / 404 Not Found Route
+
+```javascript
+{
+ // Will match everything and put it under `$route.params.pathMatch`
+ path: '/:pathMatch(.*)*',
+ name: 'NotFound',
+ component: NotFound
+}
+```
+
+## Nested Routes
+
+```javascript
+const routes = [
+ {
+ path: '/user/:id',
+ component: User,
+ children: [
+ {
+ // UserProfile will be rendered inside User's
+ // when /user/:id/profile is matched
+ path: 'profile',
+ component: UserProfile
+ },
+ {
+ // UserPosts will be rendered inside User's
+ // when /user/:id/posts is matched
+ path: 'posts',
+ component: UserPosts
+ },
+ {
+ // Redirect /user/:id to /user/:id/profile
+ path: '',
+ redirect: 'profile'
+ }
+ ]
+ }
+]
+```
+
+## Programmatic Navigation
+
+### Navigation Methods
+
+```javascript
+// Navigate to a different URL
+router.push('/users/1')
+
+// Navigate with object
+router.push({ path: '/users/1' })
+
+// Named route
+router.push({ name: 'user', params: { id: '1' } })
+
+// With query parameters
+router.push({ path: '/users', query: { page: '1' } })
+
+// Replace current entry (no browser history)
+router.replace({ path: '/home' })
+
+// Go forward/back
+router.go(1) // forward 1 page
+router.go(-1) // back 1 page
+```
+
+### In Component Methods
+
+```javascript
+// Options API
+methods: {
+ goToUser() {
+ this.$router.push('/users/1')
+ }
+}
+
+// Composition API
+import { useRouter } from 'vue-router'
+
+export default {
+ setup() {
+ const router = useRouter()
+
+ const goToUser = () => {
+ router.push('/users/1')
+ }
+
+ return { goToUser }
+ }
+}
+```
+
+## Named Routes & Views
+
+### Named Routes
+
+```javascript
+const routes = [
+ {
+ path: '/user/:id',
+ name: 'user',
+ component: User
+ }
+]
+
+// Navigation
+router.push({ name: 'user', params: { id: 1 } })
+```
+
+### Named Views
+
+```vue
+
+
+
App Layout
+
+
+
+
+
+
+
+```
+
+## Route Parameters & Props
+
+### Boolean Mode
+
+```javascript
+const routes = [
+ {
+ path: '/user/:id',
+ component: User,
+ props: true // Pass route.params as props
+ }
+]
+```
+
+### Object Mode
+
+```javascript
+const routes = [
+ {
+ path: '/user',
+ component: User,
+ props: { default: true, id: '123' }
+ }
+]
+```
+
+### Function Mode
+
+```javascript
+const routes = [
+ {
+ path: '/search',
+ component: Search,
+ props: route => ({ query: route.query.q })
+ }
+]
+```
+
+## Navigation Guards
+
+### Global Before Guards
+
+```javascript
+const router = createRouter({ ... })
+
+router.beforeEach((to, from, next) => {
+ // Must call `next`
+ if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
+ else next()
+})
+```
+
+### Per-Route Guards
+
+```javascript
+const routes = [
+ {
+ path: '/admin',
+ component: Admin,
+ beforeEnter: (to, from, next) => {
+ if (isAdmin) next()
+ else next('/login')
+ }
+ }
+]
+```
+
+### In-Component Guards
+
+```javascript
+const UserDetails = {
+ template: '...',
+ beforeRouteEnter(to, from, next) {
+ // Called before the route that renders this component is confirmed.
+ // Does NOT have access to `this` component instance.
+ next(vm => {
+ // Access component instance via `vm`
+ })
+ },
+ beforeRouteUpdate(to, from) {
+ // Called when the route that renders this component has changed,
+ // but this component is reused in the new route.
+ // Has access to `this` component instance.
+ this.userData = fetchUser(to.params.id)
+ },
+ beforeRouteLeave(to, from) {
+ // Called when the route that renders this component is about to
+ // be navigated away from.
+ const answer = window.confirm('Do you really want to leave?')
+ if (!answer) return false
+ }
+}
+```
+
+## Route Meta Fields
+
+```javascript
+const routes = [
+ {
+ path: '/profile',
+ component: Profile,
+ meta: { requiresAuth: true }
+ },
+ {
+ path: '/admin',
+ component: Admin,
+ meta: { requiresAdmin: true }
+ }
+]
+
+// Navigation guard example
+router.beforeEach((to, from, next) => {
+ if (to.meta.requiresAuth && !isAuthenticated) {
+ next('/login')
+ } else if (to.meta.requiresAdmin && !isAdmin) {
+ next('/unauthorized')
+ } else {
+ next()
+ }
+})
+```
+
+## Transitions
+
+### Per-Route Transition
+
+```vue
+
+
+
+
+
+
+
+
+
+```
+
+### Different Transitions per Route
+
+```vue
+
+
+
+
+
+
+
+```
+
+## Data Fetching
+
+### Fetching Before Navigation
+
+```javascript
+const routes = [
+ {
+ path: '/user/:id',
+ component: User,
+ props: true,
+ beforeEnter: async (to, from, next) => {
+ try {
+ const user = await fetchUser(to.params.id)
+ to.meta.user = user
+ next()
+ } catch (error) {
+ next('/error')
+ }
+ }
+ }
+]
+```
+
+### Fetching After Navigation
+
+```vue
+
+
+
{{ user.name }}
+
+
+ {{ error }}
+
+
+ Loading...
+
+
+
+
+```
+
+## Scroll Behavior
+
+```javascript
+const router = createRouter({
+ history: createWebHistory(),
+ routes,
+ scrollBehavior(to, from, savedPosition) {
+ // Scroll to top for all route navigations
+ if (savedPosition) {
+ return savedPosition
+ } else if (to.hash) {
+ return {
+ el: to.hash,
+ behavior: 'smooth',
+ }
+ } else {
+ return { top: 0, behavior: 'smooth' }
+ }
+ }
+})
+```
+
+## Lazy Loading Routes
+
+### Dynamic Imports
+
+```javascript
+const routes = [
+ {
+ path: '/about',
+ name: 'About',
+ component: () => import('../views/About.vue')
+ },
+ {
+ path: '/contact',
+ name: 'Contact',
+ component: () => import(/* webpackChunkName: "contact" */ '../views/Contact.vue')
+ }
+]
+```
+
+### Grouping Components in the Same Chunk
+
+```javascript
+// webpackChunkName comments put these in the same chunk
+const UserDetails = () => import(/* webpackChunkName: "users" */ './UserDetails.vue')
+const UserPosts = () => import(/* webpackChunkName: "users" */ './UserPosts.vue')
+```
+
+## Navigation Failures
+
+### Detecting Navigation Failures
+
+```javascript
+// After navigation
+const navigationResult = await router.push('/some-path')
+
+if (navigationResult) {
+ // Navigation was prevented
+ console.log('Navigation was prevented')
+
+ if (isNavigationFailure(navigationResult, NavigationFailureType.aborted)) {
+ console.log('Navigation was aborted')
+ } else if (isNavigationFailure(navigationResult, NavigationFailureType.cancelled)) {
+ console.log('Navigation was cancelled')
+ }
+} else {
+ // Navigation was successful
+ console.log('Navigation succeeded')
+}
+```
+
+## Composition API
+
+### useRouter & useRoute
+
+```vue
+
+
+ Current route: {{ route.path }}
+
+
+
+```
+
+## TypeScript Support
+
+### Typed Routes
+
+```typescript
+// router/index.ts
+import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
+
+const routes: Array = [
+ {
+ path: '/',
+ name: 'Home',
+ component: () => import('../views/Home.vue')
+ },
+ {
+ path: '/about',
+ name: 'About',
+ component: () => import('../views/About.vue')
+ }
+]
+
+const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes
+})
+
+export default router
+```
+
+### Typed Navigation
+
+```typescript
+import { useRouter } from 'vue-router'
+
+declare module 'vue-router' {
+ interface RouteMeta {
+ requiresAuth?: boolean
+ requiresAdmin?: boolean
+ }
+}
+
+const router = useRouter()
+
+// Typed navigation
+router.push({
+ name: 'UserProfile',
+ params: { id: 1 } // Type-checked
+})
+```
+
+## Authentication & Protected Routes
+
+### Route Guard for Authentication
+
+```typescript
+// router/guards/authGuard.ts
+import { NavigationGuardNext, RouteLocationNormalized } from 'vue-router'
+import { useAuthStore } from '@/stores/auth'
+
+export default function authGuard(
+ to: RouteLocationNormalized,
+ from: RouteLocationNormalized,
+ next: NavigationGuardNext
+) {
+ const authStore = useAuthStore()
+
+ if (to.meta.requiresAuth && !authStore.isAuthenticated) {
+ next({
+ name: 'Login',
+ query: { redirect: to.fullPath }
+ })
+ } else if (to.meta.requiresAdmin && !authStore.isAdmin) {
+ next({ name: 'Unauthorized' })
+ } else {
+ next()
+ }
+}
+```
+
+### Login Flow
+
+```vue
+
+
+
+
+
+```
+
+## Error Handling
+
+### 404 Not Found
+
+```javascript
+// router/index.js
+const routes = [
+ // ... other routes ...
+ {
+ path: '/:pathMatch(.*)*',
+ name: 'NotFound',
+ component: () => import('@/views/NotFound.vue')
+ }
+]
+```
+
+### Global Error Handler
+
+```javascript
+// main.js
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+
+const app = createApp(App)
+
+// Global error handler for navigation errors
+app.config.errorHandler = (err, vm, info) => {
+ console.error('Vue error:', err)
+ console.error('Error in component:', vm)
+ console.error('Error info:', info)
+
+ // You could redirect to an error page here
+ // router.push('/error')
+}
+
+// Global error handler for unhandled promise rejections
+window.addEventListener('unhandledrejection', (event) => {
+ console.error('Unhandled promise rejection:', event.reason)
+ // Prevent the default browser error handling
+ event.preventDefault()
+})
+
+app.use(router)
+app.mount('#app')
+```
+
+## Performance Optimization
+
+### Route-Level Code Splitting
+
+```javascript
+const routes = [
+ {
+ path: '/dashboard',
+ component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue')
+ },
+ {
+ path: '/settings',
+ component: () => import(/* webpackChunkName: "settings" */ '@/views/Settings.vue')
+ }
+]
+```
+
+### Prefetching Routes
+
+```vue
+
+
+
+ Dashboard
+
+
+
+
+
+```
+
+### Lazy Loading with Suspense
+
+```vue
+
+
+
+
+
+
+ Loading...
+
+
+
+```
+
+## Deployment
+
+### History Mode Server Configuration
+
+#### Nginx
+
+```nginx
+location / {
+ try_files $uri $uri/ /index.html;
+}
+```
+
+#### Apache
+
+```apache
+
+ RewriteEngine On
+ RewriteBase /
+ RewriteRule ^index\.html$ - [L]
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteRule . /index.html [L]
+
+```
+
+### Base URL
+
+```javascript
+const router = createRouter({
+ history: createWebHistory('/my-app/'),
+ routes
+})
+```
+
+## Common Patterns
+
+### Route-Based Code Splitting
+
+```javascript
+// router/modules/admin.js
+const AdminDashboard = () => import('@/views/admin/Dashboard.vue')
+const AdminUsers = () => import('@/views/admin/Users.vue')
+
+export default [
+ {
+ path: '/admin',
+ component: () => import('@/layouts/AdminLayout.vue'),
+ children: [
+ { path: '', component: AdminDashboard },
+ { path: 'users', component: AdminUsers }
+ ]
+ }
+]
+```
+
+### Scroll to Top on Route Change
+
+```javascript
+const router = createRouter({
+ // ...
+ scrollBehavior(to, from, savedPosition) {
+ if (savedPosition) {
+ return savedPosition
+ } else {
+ return { top: 0, behavior: 'smooth' }
+ }
+ }
+})
+```
+
+### Query Parameter Changes
+
+```vue
+
+
+
+
+
+```
+
+## Migration from Vue 2
+
+### Key Changes in Vue Router 4
+
+1. **New `createRouter` function**
+ ```javascript
+ // Vue Router 3
+ const router = new VueRouter({ ... })
+
+ // Vue Router 4
+ import { createRouter, createWebHistory } from 'vue-router'
+ const router = createRouter({
+ history: createWebHistory(),
+ routes: []
+ })
+ ```
+
+2. **New Navigation API**
+ ```javascript
+ // Vue Router 3
+ this.$router.push('/path')
+
+ // Vue Router 4 (Composition API)
+ import { useRouter } from 'vue-router'
+ const router = useRouter()
+ router.push('/path')
+ ```
+
+3. **Route Properties**
+ - `$route` is now accessed via `useRoute()` in Composition API
+ - `parent` and `children` properties are removed from route records
+
+4. **Navigation Guards**
+ - `next` parameter is now optional in navigation guards
+ - `next(false)` is now `return false`
+ - `next('/')` is now `return '/'`
+
+5. **Scroll Behavior**
+ - The `x` and `y` properties are now `left` and `top`
+ - The `selector` option is replaced with `el`
+
+### Migration Strategy
+
+1. Update Vue Router to version 4
+ ```bash
+ npm install vue-router@4
+ # or
+ yarn add vue-router@4
+ ```
+
+2. Update your router configuration
+ - Replace `new VueRouter()` with `createRouter()`
+ - Replace `mode: 'history'` with `history: createWebHistory()`
+ - Update any scroll behavior functions
+
+3. Update your components
+ - Replace `this.$route` with `useRoute()` in setup()
+ - Replace `this.$router` with `useRouter()` in setup()
+ - Update any navigation guards
+
+4. Test thoroughly
+ - Test all navigation flows
+ - Check for any direct route property access
+ - Verify scroll behavior
+
+5. Update tests
+ - Update any tests that interact with the router
+ - Use the new testing utilities if needed
+
+## Conclusion
+
+Vue Router is a powerful and flexible routing library for Vue.js applications. By following the patterns and best practices outlined in this guide, you can build complex, maintainable, and performant single-page applications. Whether you're building a small project or a large-scale application, Vue Router provides the tools you need to manage navigation and state effectively.
diff --git a/docs/vue/setup.md b/docs/vue/setup.md
new file mode 100644
index 0000000..21d6bae
--- /dev/null
+++ b/docs/vue/setup.md
@@ -0,0 +1,323 @@
+# Vue.js Setup Guide
+
+## Table of Contents
+1. [Installation](#installation)
+2. [Project Setup](#project-setup)
+3. [Vue CLI](#vue-cli)
+4. [Vite](#vite)
+5. [CDN](#cdn)
+6. [Development Server](#development-server)
+7. [Build for Production](#build-for-production)
+8. [Configuration](#configuration)
+9. [IDE Setup](#ide-setup)
+10. [Browser DevTools](#browser-devtools)
+
+## Installation
+
+### Prerequisites
+- Node.js 16.0.0 or later
+- npm or yarn
+
+### Vue CLI (Legacy)
+```bash
+# Install Vue CLI globally
+npm install -g @vue/cli
+# OR
+yarn global add @vue/cli
+
+# Check installation
+vue --version
+```
+
+### Create a New Project
+#### Using Vue CLI
+```bash
+vue create my-vue-app
+cd my-vue-app
+```
+
+#### Using Vite (Recommended for new projects)
+```bash
+# npm 7+, extra double-dash is needed:
+npm create vue@latest my-vue-app -- --typescript --router --pinia --vitest --eslint
+
+# npm 6.x
+npm create vue@latest my-vue-app --template typescript --router --pinia --vitest --eslint
+
+# yarn
+yarn create vue my-vue-app --template typescript --router --pinia --vitest --eslint
+
+# pnpm
+pnpm create vue my-vue-app -- --typescript --router --pinia --vitest --eslint
+
+# Navigate to project
+cd my-vue-app
+
+# Install dependencies
+npm install
+# OR
+yarn
+# OR
+pnpm install
+```
+
+## Project Structure
+
+### Vue 3 Project Structure
+```
+my-vue-app/
+├── public/ # Static files
+│ ├── favicon.ico
+│ └── index.html # Main HTML file
+├── src/
+│ ├── assets/ # Static assets (images, styles)
+│ ├── components/ # Reusable components
+│ ├── composables/ # Composable functions
+│ ├── router/ # Vue Router configuration
+│ ├── stores/ # State management (Pinia)
+│ ├── views/ # Route components
+│ ├── App.vue # Root component
+│ └── main.js # Application entry point
+├── .eslintrc.js # ESLint config
+├── .gitignore
+├── index.html
+├── package.json
+├── README.md
+├── vite.config.js # Vite config
+└── tsconfig.json # TypeScript config
+```
+
+### Main Application File
+```typescript
+// src/main.ts
+import { createApp } from 'vue'
+import { createPinia } from 'pinia'
+import App from './App.vue'
+import router from './router'
+
+// Import global styles
+import './assets/main.css'
+
+const app = createApp(App)
+
+// Use plugins
+app.use(createPinia())
+app.use(router)
+
+// Mount the app
+app.mount('#app')
+```
+
+## CDN
+
+### Development Version
+```html
+
+
+```
+
+### Production Version
+```html
+
+
+```
+
+### ES Modules Build
+```html
+
+```
+
+## Development Server
+
+### Vite Dev Server
+```bash
+# Start development server
+npm run dev
+# OR
+yarn dev
+# OR
+pnpm dev
+
+# Access at http://localhost:5173
+```
+
+### Vue CLI Dev Server (legacy)
+```bash
+npm run serve
+# OR
+yarn serve
+```
+
+## Build for Production
+
+### Vite Build
+```bash
+# Build for production
+npm run build
+# OR
+yarn build
+# OR
+pnpm build
+
+# Preview production build locally
+npm run preview
+```
+
+### Vue CLI Build (legacy)
+```bash
+npm run build
+# OR
+yarn build
+```
+
+## Configuration
+
+### Vite Configuration (vite.config.js)
+```javascript
+import { fileURLToPath, URL } from 'node:url'
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [vue()],
+ resolve: {
+ alias: {
+ '@': fileURLToPath(new URL('./src', import.meta.url))
+ }
+ },
+ server: {
+ port: 3000,
+ open: true
+ },
+ build: {
+ outDir: 'dist',
+ assetsDir: 'assets',
+ sourcemap: true
+ }
+})
+```
+
+### Environment Variables
+Create `.env` files in your project root:
+
+```env
+# .env
+VITE_APP_TITLE=My Vue App
+VITE_API_URL=https://api.example.com
+```
+
+Access in your code:
+```typescript
+const apiUrl = import.meta.env.VITE_API_URL
+```
+
+## IDE Setup
+
+### VS Code Extensions
+1. [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) - Official Vue Language Features
+2. [TypeScript Vue Plugin](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) - TypeScript support for Vue
+3. [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - JavaScript/TypeScript linting
+4. [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - Code formatter
+5. [Stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) - CSS/SCSS linting
+
+### Recommended VS Code Settings
+```json
+{
+ "editor.tabSize": 2,
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true,
+ "source.organizeImports": true
+ },
+ "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "vue"],
+ "[vue]": {
+ "editor.defaultFormatter": "Vue.volar"
+ },
+ "typescript.tsdk": "node_modules/typescript/lib"
+}
+```
+
+## Browser DevTools
+
+### Vue Devtools
+1. Install [Vue Devtools](https://devtools.vuejs.org/guide/installation.html) browser extension
+2. For local development, it should automatically detect your Vue application
+3. For production, add this to your main application file:
+
+```typescript
+// Only in development
+if (import.meta.env.DEV) {
+ const { createApp } = await import('vue')
+ const { default: App } = await import('./App.vue')
+
+ // Mount devtools
+ if (window.__VUE_DEVTOOLS_GLOBAL_HOOK__) {
+ window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = createApp
+ }
+}
+```
+
+### Debugging
+- Use `debugger` statements in your code
+- Utilize Vue Devtools component inspection
+- Check the browser's console for warnings and errors
+
+## Common Issues
+
+### Resolving Dependency Issues
+```bash
+# Delete node_modules and package-lock.json
+rm -rf node_modules package-lock.json
+
+# Clear npm cache
+npm cache clean --force
+
+# Reinstall dependencies
+npm install
+```
+
+### TypeScript Support
+Ensure your `tsconfig.json` includes:
+```json
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "strict": true,
+ "jsx": "preserve",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "lib": ["ESNext", "DOM"],
+ "skipLibCheck": true,
+ "noEmit": true,
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
+```
+
+### Vue 2 vs Vue 3
+- Vue 3 is the current major version with Composition API
+- Vue 2 is in maintenance mode (end of life: Dec 31, 2023)
+- Use `@vue/compat` for migration from Vue 2 to 3
+
+## Next Steps
+- [Learn about Components](./components.md)
+- [Understand Reactivity System](./reactivity.md)
+- [State Management with Pinia/Vuex](./vuex.md)
+- [Routing with Vue Router](./routing.md)
diff --git a/docs/vue/vuex.md b/docs/vue/vuex.md
new file mode 100644
index 0000000..b358be6
--- /dev/null
+++ b/docs/vue/vuex.md
@@ -0,0 +1,502 @@
+# Vuex: State Management for Vue.js
+
+## Table of Contents
+- [Introduction to Vuex](#introduction-to-vuex)
+- [Core Concepts](#core-concepts)
+ - [State](#state)
+ - [Getters](#getters)
+ - [Mutations](#mutations)
+ - [Actions](#actions)
+ - [Modules](#modules)
+- [Setting Up Vuex](#setting-up-vuex)
+- [Basic Usage](#basic-usage)
+- [Advanced Patterns](#advanced-patterns)
+- [Composition API with Vuex](#composition-api-with-vuex)
+- [Testing Vuex](#testing-vuex)
+- [Vuex vs. Pinia](#vuex-vs-pinia)
+- [Best Practices](#best-practices)
+- [Migration from Vuex 3 to 4](#migration-from-vuex-3-to-4)
+- [Common Pitfalls](#common-pitfalls)
+- [Performance Optimization](#performance-optimization)
+- [Useful Plugins](#useful-plugins)
+
+## Introduction to Vuex
+
+Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.
+
+### When to Use Vuex
+- Large-scale applications with complex state management needs
+- Multiple components need to share state
+- State needs to be accessed by many components at different nesting levels
+- State needs to be preserved across page reloads
+- State needs to be tracked and debugged
+
+## Core Concepts
+
+### State
+
+```javascript
+const store = createStore({
+ state: {
+ count: 0,
+ todos: []
+ }
+})
+```
+
+### Getters
+
+```javascript
+const store = createStore({
+ state: {
+ todos: [
+ { id: 1, text: 'Learn Vue', done: true },
+ { id: 2, text: 'Learn Vuex', done: false }
+ ]
+ },
+ getters: {
+ doneTodos: (state) => {
+ return state.todos.filter(todo => todo.done)
+ },
+ getTodoById: (state) => (id) => {
+ return state.todos.find(todo => todo.id === id)
+ }
+ }
+})
+```
+
+### Mutations
+
+```javascript
+const store = createStore({
+ state: {
+ count: 1
+ },
+ mutations: {
+ increment (state) {
+ state.count++
+ },
+ incrementBy (state, payload) {
+ state.count += payload.amount
+ }
+ }
+})
+
+// Commit a mutation
+store.commit('increment')
+store.commit('incrementBy', { amount: 10 })
+```
+
+### Actions
+
+```javascript
+const store = createStore({
+ state: {
+ count: 0
+ },
+ mutations: {
+ increment (state) {
+ state.count++
+ }
+ },
+ actions: {
+ incrementAsync ({ commit }) {
+ setTimeout(() => {
+ commit('increment')
+ }, 1000)
+ },
+ async fetchData({ commit }) {
+ try {
+ const response = await fetch('api/data')
+ const data = await response.json()
+ commit('setData', data)
+ } catch (error) {
+ console.error('Error fetching data:', error)
+ }
+ }
+ }
+})
+
+// Dispatch an action
+store.dispatch('incrementAsync')
+```
+
+### Modules
+
+```javascript
+const moduleA = {
+ namespaced: true,
+ state: { count: 0 },
+ mutations: {
+ increment (state) {
+ state.count++
+ }
+ },
+ getters: {
+ doubleCount (state) {
+ return state.count * 2
+ }
+ }
+}
+
+const store = createStore({
+ modules: {
+ a: moduleA
+ }
+})
+
+// Access module state
+store.state.a.count
+
+// Access module getter
+store.getters['a/doubleCount']
+
+// Commit module mutation
+store.commit('a/increment')
+
+// Dispatch module action
+store.dispatch('a/incrementAsync')
+```
+
+## Setting Up Vuex
+
+### Installation
+
+```bash
+# For Vue 3
+npm install vuex@next --save
+# or with yarn
+yarn add vuex@next
+```
+
+### Basic Store
+
+```javascript
+import { createApp } from 'vue'
+import { createStore } from 'vuex'
+
+const store = createStore({
+ state: {
+ count: 0
+ },
+ mutations: {
+ increment (state) {
+ state.count++
+ }
+ },
+ actions: {
+ incrementAsync ({ commit }) {
+ setTimeout(() => {
+ commit('increment')
+ }, 1000)
+ }
+ },
+ getters: {
+ getCount: state => state.count
+ }
+})
+
+const app = createApp({ /* your root component */ })
+app.use(store)
+app.mount('#app')
+```
+
+## Composition API with Vuex
+
+```vue
+
+
+
Count: {{ count }}
+
Double: {{ doubleCount }}
+
+
+
+
+
+
+```
+
+## Testing Vuex
+
+### Testing Mutations
+
+```javascript
+import { createStore } from 'vuex'
+import { mutations } from '@/store/mutations'
+
+describe('mutations', () => {
+ let store
+
+ beforeEach(() => {
+ store = createStore({
+ state: { count: 0 },
+ mutations
+ })
+ })
+
+ test('increment increments state.count by 1', () => {
+ store.commit('increment')
+ expect(store.state.count).toBe(1)
+ })
+})
+```
+
+### Testing Actions
+
+```javascript
+import { createStore } from 'vuex'
+import { actions } from '@/store/actions'
+
+// Mock API or service
+jest.mock('@/api', () => ({
+ fetchData: jest.fn(() => Promise.resolve({ data: 'mocked data' }))
+}))
+
+describe('actions', () => {
+ let store
+
+ beforeEach(() => {
+ store = createStore({
+ state: { data: null },
+ mutations: {
+ setData: (state, data) => { state.data = data }
+ },
+ actions
+ })
+ })
+
+ test('fetchData commits the response', async () => {
+ await store.dispatch('fetchData')
+ expect(store.state.data).toBe('mocked data')
+ })
+})
+```
+
+## Vuex vs. Pinia
+
+| Feature | Vuex | Pinia |
+|---------|------|-------|
+| Vue 3 Support | Vuex 4+ | Built for Vue 3 |
+| TypeScript | Partial | First-class |
+| DevTools | Yes | Yes |
+| Composition API | Yes | Built with it |
+| Size | ~1.5KB | ~1KB |
+| Modules | Required | Optional |
+| Code Splitting | Manual | Automatic |
+
+## Best Practices
+
+1. **Strict Mode**
+ ```javascript
+ const store = createStore({
+ // ...
+ strict: process.env.NODE_ENV !== 'production'
+ })
+ ```
+
+2. **Use Constants for Mutation Types**
+ ```javascript
+ // mutation-types.js
+ export const SOME_MUTATION = 'SOME_MUTATION'
+
+ // store.js
+ import { SOME_MUTATION } from './mutation-types'
+
+ const store = createStore({
+ state: { ... },
+ mutations: {
+ [SOME_MUTATION] (state) {
+ // mutate state
+ }
+ }
+ })
+ ```
+
+3. **Organize with Modules**
+ ```
+ store/
+ ├── index.js # where we assemble modules and export the store
+ ├── actions.js # root actions
+ ├── mutations.js # root mutations
+ └── modules/
+ ├── cart.js # cart module
+ └── products.js # products module
+ ```
+
+4. **Use Action Composition**
+ ```javascript
+ actions: {
+ async actionA ({ commit }) {
+ commit('gotData', await getData())
+ },
+ async actionB ({ dispatch, commit }) {
+ await dispatch('actionA') // wait for actionA to finish
+ commit('gotOtherData', await getOtherData())
+ }
+ }
+ ```
+
+## Migration from Vuex 3 to 4
+
+1. **Installation**
+ ```bash
+ npm install vuex@next
+ ```
+
+2. **Breaking Changes**
+ - Vue 3 compatibility only
+ - New `createStore` function instead of `new Vuex.Store`
+ - TypeScript improvements
+ - `store.subscribeAction` now receives an object with `before` and `after` hooks
+
+## Common Pitfalls
+
+1. **Mutating State Outside Mutations**
+ ```javascript
+ // Bad
+ store.state.count = 10
+
+ // Good
+ store.commit('setCount', 10)
+ ```
+
+2. **Not Using Getters for Derived State**
+ ```javascript
+ // Bad - computed property in component
+ computed: {
+ completedTodos() {
+ return this.$store.state.todos.filter(todo => todo.completed)
+ }
+ }
+
+ // Good - using getter
+ computed: {
+ completedTodos() {
+ return this.$store.getters.completedTodos
+ }
+ }
+ ```
+
+3. **Overusing Vuex**
+ - Use component local state for component-specific state
+ - Use props/events for parent-child communication
+ - Use provide/inject for dependency injection
+ - Use Vuex for global state that needs to be shared across components
+
+## Performance Optimization
+
+1. **Use `mapState` with Care**
+ ```javascript
+ // Instead of this (creates a new computed property for each state property)
+ ...mapState(['a', 'b', 'c'])
+
+ // Do this (single computed property)
+ ...mapState({
+ state: state => ({
+ a: state.a,
+ b: state.b,
+ c: state.c
+ })
+ })
+ ```
+
+2. **Use `mapGetters` for Multiple Getters**
+ ```javascript
+ import { mapGetters } from 'vuex'
+
+ export default {
+ computed: {
+ ...mapGetters([
+ 'doneTodosCount',
+ 'anotherGetter',
+ // ...
+ ])
+ }
+ }
+ ```
+
+3. **Lazy Load Modules**
+ ```javascript
+ const store = createStore({ /* ... */ })
+
+ // Load module dynamically
+ import('./modules/cart').then(cartModule => {
+ store.registerModule('cart', cartModule.default)
+ })
+ ```
+
+## Useful Plugins
+
+1. **vuex-persistedstate**
+ ```bash
+ npm install --save vuex-persistedstate
+ ```
+
+ ```javascript
+ import createPersistedState from 'vuex-persistedstate'
+
+ const store = createStore({
+ // ...
+ plugins: [
+ createPersistedState({
+ key: 'my-app',
+ paths: ['user', 'settings']
+ })
+ ]
+ })
+ ```
+
+2. **vuex-router-sync**
+ ```bash
+ npm install vuex-router-sync@next
+ ```
+
+ ```javascript
+ import { sync } from 'vuex-router-sync'
+ import store from './store'
+ import router from './router'
+
+ sync(store, router)
+ ```
+
+3. **vuex-shared-mutations**
+ ```bash
+ npm install --save vuex-shared-mutations
+ ```
+
+ ```javascript
+ import createMutationsSharer from 'vuex-shared-mutations'
+
+ const store = createStore({
+ // ...
+ plugins: [
+ createMutationsSharer({
+ predicate: [
+ 'increment',
+ 'decrement',
+ 'setUser'
+ ]
+ })
+ ]
+ })
+ ```
+
+## Conclusion
+
+Vuex provides a robust solution for state management in Vue.js applications. While newer solutions like Pinia offer a more modern API, Vuex remains a solid choice, especially for existing projects. By following the patterns and best practices outlined in this guide, you can build maintainable and scalable Vue.js applications with Vuex.