Files
manja_ui_dev/DEVELOPMENT.md
T
mrholek 7e6a087049 docs: add AI-friendly documentation and code comments
Add comprehensive documentation for AI assistants:
- .cursorrules with project context and conventions
- ARCHITECTURE.md with technical details
- DEVELOPMENT.md with practical guides
- JSDoc comments in all JavaScript modules
- Update README.md with AI-Friendly Development section

This enables AI tools (Cursor, Claude Code, GitHub Copilot) to understand the project and generate code following CoreUI Vue patterns.
2026-04-01 10:47:02 +02:00

1114 lines
22 KiB
Markdown

# CoreUI Free Vue Admin Template - Development Guide
A comprehensive guide for developers working with the CoreUI Free Vue Admin Template. This guide covers setup, development workflows, common patterns, and best practices.
## Table of Contents
- [Prerequisites](#prerequisites)
- [Getting Started](#getting-started)
- [Project Structure](#project-structure)
- [Development Workflow](#development-workflow)
- [Creating Components](#creating-components)
- [Adding New Pages](#adding-new-pages)
- [Working with Routes](#working-with-routes)
- [State Management](#state-management)
- [Styling Components](#styling-components)
- [Working with Forms](#working-with-forms)
- [Data Visualization](#data-visualization)
- [Code Quality](#code-quality)
- [Testing](#testing)
- [Build and Deployment](#build-and-deployment)
- [Troubleshooting](#troubleshooting)
- [Best Practices](#best-practices)
## Prerequisites
### Required Software
- **Node.js**: Version 16 or higher (18+ recommended)
- **npm**: Version 7+ or **yarn**: Version 1.22+
- **Git**: For version control
### Recommended Tools
- **Visual Studio Code** with extensions:
- Volar (Vue Language Features)
- ESLint
- Prettier
- Auto Import
- GitLens
- **Vue DevTools** browser extension
### Knowledge Requirements
- JavaScript ES6+ features (arrow functions, destructuring, modules)
- Vue 3 fundamentals (Composition API, reactive, ref, computed)
- HTML5 and CSS3
- Sass/SCSS basics
- Git version control
## Getting Started
### Installation
1. **Clone the repository** (or download the source):
```bash
git clone https://github.com/coreui/coreui-free-vue-admin-template.git
cd coreui-free-vue-admin-template
```
2. **Install dependencies**:
```bash
npm install
# or
yarn install
```
3. **Start the development server**:
```bash
npm run dev
# or
yarn dev
```
4. **Open your browser** to [http://localhost:3000](http://localhost:3000)
The development server includes:
- Hot Module Replacement (HMR) for instant updates
- Automatic browser refresh on file changes
- Error overlay for compile-time and runtime errors
### Available Scripts
| Command | Description |
|---------|-------------|
| `npm run dev` | Start development server on port 3000 |
| `npm run build` | Build optimized production bundle |
| `npm run preview` | Preview production build locally |
| `npm run lint` | Run ESLint to check code quality |
## Project Structure
### Source Code Organization
**IMPORTANT**: Always edit source files in `src/`, never modify compiled files in `dist/`.
```
src/
├── assets/ # Static assets (images, logos)
├── components/ # Reusable UI components
├── layouts/ # Layout wrapper components
├── views/ # Page/route components
├── router/ # Router configuration
├── stores/ # Pinia stores (optional)
├── scss/ # Global styles and themes
├── App.vue # Root component
├── main.js # Application entry point
└── _nav.js # Navigation menu configuration
```
### Key Files
- **`App.vue`**: Main application component with router-view
- **`main.js`**: Vue app creation, plugins, and mounting
- **`router/index.js`**: Route definitions and configuration
- **`_nav.js`**: Navigation menu structure for sidebar
## Development Workflow
### Daily Development Process
1. **Start development server**: `npm run dev`
2. **Make changes** to source files in `src/`
3. **View changes** instantly in browser (HMR)
4. **Check console** for errors or warnings
5. **Run linter** before committing: `npm run lint`
6. **Test in both themes** (light and dark)
7. **Commit changes** with conventional commit messages
### Hot Module Replacement (HMR)
Vite provides instant feedback:
- **Vue SFC changes**: Component updates without page reload
- **CSS/SCSS changes**: Style updates without reload
- **Configuration changes**: Require server restart
### Development Server Features
**Port**: 3000 (configurable in `vite.config.mjs`)
**Features**:
- Fast cold start (~500ms)
- Instant HMR (<50ms)
- Error overlay with stack traces
- Network access for mobile testing
**Access from mobile**:
```bash
# Find your local IP
# Windows: ipconfig
# Mac/Linux: ifconfig
# Access from mobile device:
http://192.168.1.X:3000
```
## Creating Components
### Component Structure
**Composition API with script setup**:
```vue
<template>
<CCard>
<CCardHeader>{{ name }}</CCardHeader>
<CCardBody>
<img v-if="avatar" :src="avatar" :alt="name" />
<p>{{ email }}</p>
</CCardBody>
</CCard>
</template>
<script setup>
/**
* UserCard component displays user information in a card format
*/
import { defineProps } from 'vue'
const props = defineProps({
/** User's full name */
name: {
type: String,
required: true,
},
/** User's email address */
email: {
type: String,
required: true,
},
/** Optional avatar URL */
avatar: {
type: String,
default: null,
},
})
</script>
<style scoped>
/* Component-specific styles */
</style>
```
### Component Best Practices
1. **Keep components focused**: One responsibility per component
2. **Use prop validation**: Define types and required props
3. **Add JSDoc comments**: Document component purpose and props
4. **Extract logic**: Use composables for reusable logic
5. **Name meaningfully**: Clear, descriptive component names
### Composables (Custom Hooks)
Extract reusable logic into composables:
```javascript
// composables/useFetch.js
import { ref, watch } from 'vue'
/**
* Custom composable for fetching data from an API
* @param {String} url - API endpoint URL
* @returns {Object} { data, loading, error, refetch }
*/
export function useFetch(url) {
const data = ref(null)
const loading = ref(true)
const error = ref(null)
const fetchData = async () => {
try {
loading.value = true
const response = await fetch(url)
data.value = await response.json()
error.value = null
} catch (err) {
error.value = err.message
} finally {
loading.value = false
}
}
watch(() => url, fetchData, { immediate: true })
return { data, loading, error, refetch: fetchData }
}
```
**Usage**:
```vue
<script setup>
import { useFetch } from '@/composables/useFetch'
const { data, loading, error } = useFetch('/api/users')
</script>
<template>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error }}</div>
<div v-else>{{ data }}</div>
</template>
```
## Adding New Pages
### Step-by-Step Process
**1. Create the page component** in `src/views/[feature]/`:
```vue
<!-- src/views/products/Products.vue -->
<template>
<CRow>
<CCol :xs="12">
<CCard class="mb-4">
<CCardHeader>
<strong>Products</strong>
</CCardHeader>
<CCardBody>
<!-- Your content here -->
</CCardBody>
</CCard>
</CCol>
</CRow>
</template>
<script setup>
// Component logic
</script>
```
**2. Add route to `src/router/index.js`**:
```javascript
{
path: '/products',
name: 'Products',
component: () => import('@/views/products/Products.vue'),
}
```
**3. Add navigation item to `src/_nav.js`** (optional):
```javascript
{
component: 'CNavItem',
name: 'Products',
to: '/products',
icon: 'cil-basket',
}
```
**4. Test the page**:
- Navigate to `http://localhost:3000/#/products`
- Check that navigation highlights correctly
- Verify breadcrumb displays properly
### Page Templates
**List Page**:
```vue
<template>
<CCard>
<CCardHeader>Items</CCardHeader>
<CCardBody>
<CTable>
<CTableHead>
<CTableRow>
<CTableHeaderCell>Name</CTableHeaderCell>
<CTableHeaderCell>Status</CTableHeaderCell>
</CTableRow>
</CTableHead>
<CTableBody>
<CTableRow v-for="item in items" :key="item.id">
<CTableDataCell>{{ item.name }}</CTableDataCell>
<CTableDataCell>{{ item.status }}</CTableDataCell>
</CTableRow>
</CTableBody>
</CTable>
</CCardBody>
</CCard>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const items = ref([])
onMounted(async () => {
// Fetch items
})
</script>
```
**Detail Page**:
```vue
<template>
<CSpinner v-if="!item" />
<CCard v-else>
<CCardHeader>{{ item.name }}</CCardHeader>
<CCardBody>
<p>{{ item.description }}</p>
</CCardBody>
</CCard>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const item = ref(null)
onMounted(async () => {
// Fetch item by route.params.id
})
</script>
```
## Working with Routes
### Route Configuration
Routes are defined in `src/router/index.js`:
```javascript
const routes = [
{
path: '/',
redirect: '/dashboard',
name: 'Home',
component: DefaultLayout,
children: [
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/Dashboard.vue'),
},
],
},
]
```
### Dynamic Routes
**With URL parameters**:
```javascript
// Route definition
{
path: '/products/:id',
name: 'Product Detail',
component: () => import('@/views/products/ProductDetail.vue'),
}
// Component usage
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const productId = route.params.id
</script>
```
### Programmatic Navigation
**Using useRouter hook**:
```vue
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const goToProducts = () => {
router.push('/products')
}
const goBack = () => {
router.back()
}
</script>
<template>
<CButton @click="goToProducts">View Products</CButton>
<CButton @click="goBack">Go Back</CButton>
</template>
```
### Protected Routes
Add authentication logic in `router/index.js`:
```javascript
router.beforeEach((to, from, next) => {
const isAuthenticated = localStorage.getItem('token')
if (to.meta.requiresAuth && !isAuthenticated) {
next('/pages/login')
} else {
next()
}
})
```
## State Management
### Using Pinia
**Creating a store**:
```javascript
// stores/main.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useStore = defineStore('main', () => {
// State
const sidebarVisible = ref(true)
const theme = ref('light')
// Getters
const isDark = computed(() => theme.value === 'dark')
// Actions
function toggleSidebar() {
sidebarVisible.value = !sidebarVisible.value
}
function setTheme(newTheme) {
theme.value = newTheme
}
return { sidebarVisible, theme, isDark, toggleSidebar, setTheme }
})
```
**Using the store**:
```vue
<script setup>
import { useStore } from '@/stores/main'
const store = useStore()
// Read state
console.log(store.sidebarVisible)
console.log(store.isDark)
// Call actions
store.toggleSidebar()
store.setTheme('dark')
</script>
```
### Local Component State
**ref for simple state**:
```vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
const isOpen = ref(false)
const formData = ref({ name: '', email: '' })
</script>
```
**reactive for complex state**:
```vue
<script setup>
import { reactive } from 'vue'
const state = reactive({
count: 0,
step: 1,
history: [],
})
</script>
```
## Styling Components
### Using CoreUI Components
**ALWAYS use CoreUI Vue components** from `@coreui/vue`:
```vue
<template>
<CRow>
<CCol :md="6">
<CCard>
<CCardHeader>Card Title</CCardHeader>
<CCardBody>
<CButton color="primary">Click Me</CButton>
</CCardBody>
</CCard>
</CCol>
</CRow>
</template>
```
### Bootstrap Utilities
Use Bootstrap utility classes for quick styling:
```vue
<template>
<CCard class="mb-4 shadow-sm">
<CCardBody class="p-4 d-flex justify-content-between align-items-center">
<span class="text-muted">Left</span>
<span class="fw-bold">Right</span>
</CCardBody>
</CCard>
</template>
```
**Common utilities**:
- Spacing: `m-3`, `mt-2`, `mb-4`, `p-3`, `px-4`, `py-2`
- Display: `d-flex`, `d-none`, `d-block`, `d-inline`
- Flexbox: `justify-content-between`, `align-items-center`
- Text: `text-center`, `text-muted`, `fw-bold`, `fs-5`
### Custom Styles
**Component-level SCSS** (scoped):
```vue
<template>
<div class="my-component">
<h1 class="my-component__title">Title</h1>
</div>
</template>
<style scoped lang="scss">
.my-component {
padding: 1rem;
background-color: var(--cui-light);
&__title {
color: var(--cui-primary);
font-size: 1.5rem;
}
}
</style>
```
### CSS Custom Properties
Use CoreUI CSS variables for theming:
```vue
<template>
<div :style="{
backgroundColor: 'var(--cui-primary)',
color: 'var(--cui-white)',
padding: 'var(--cui-spacer-3)',
}">
Styled with CSS variables
</div>
</template>
```
**Common variables**:
- Colors: `--cui-primary`, `--cui-secondary`, `--cui-success`, `--cui-danger`
- Background: `--cui-body-bg`, `--cui-light`, `--cui-dark`
- Text: `--cui-body-color`, `--cui-text-muted`
- Spacing: `--cui-spacer-1` through `--cui-spacer-5`
### Conditional Styling
Use class or style bindings:
```vue
<template>
<button
:class="['btn', { 'btn-primary': isPrimary, 'btn-secondary': !isPrimary, 'active': isActive }]"
>
Button
</button>
</template>
<script setup>
import { ref } from 'vue'
const isPrimary = ref(true)
const isActive = ref(false)
</script>
```
## Working with Forms
### Form Component Example
```vue
<template>
<CCard>
<CCardHeader>Contact Form</CCardHeader>
<CCardBody>
<CForm
class="row g-3"
:noValidate="true"
:validated="validated"
@submit.prevent="handleSubmit"
>
<CCol :md="6">
<CFormLabel for="name">Name</CFormLabel>
<CFormInput
type="text"
id="name"
v-model="formData.name"
required
/>
</CCol>
<CCol :md="6">
<CFormLabel for="email">Email</CFormLabel>
<CFormInput
type="email"
id="email"
v-model="formData.email"
required
/>
</CCol>
<CCol :xs="12">
<CFormLabel for="message">Message</CFormLabel>
<CFormTextarea
id="message"
:rows="3"
v-model="formData.message"
required
/>
</CCol>
<CCol :xs="12">
<CButton color="primary" type="submit">
Submit
</CButton>
</CCol>
</CForm>
</CCardBody>
</CCard>
</template>
<script setup>
import { ref } from 'vue'
const formData = ref({
name: '',
email: '',
message: '',
})
const validated = ref(false)
const handleSubmit = (event) => {
const form = event.target
if (!form.checkValidity()) {
validated.value = true
return
}
// Submit form data
console.log('Form data:', formData.value)
}
</script>
```
### Form Validation
**HTML5 validation**:
```vue
<CFormInput
type="email"
required
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"
/>
```
**Custom validation**:
```vue
<script setup>
import { ref } from 'vue'
const errors = ref({})
const validate = () => {
const newErrors = {}
if (!formData.value.name) {
newErrors.name = 'Name is required'
}
if (!formData.value.email.includes('@')) {
newErrors.email = 'Invalid email address'
}
errors.value = newErrors
return Object.keys(newErrors).length === 0
}
const handleSubmit = () => {
if (validate()) {
// Submit form
}
}
</script>
```
## Data Visualization
### Using Chart.js with CoreUI
```vue
<template>
<CCard>
<CCardHeader>Sales Overview</CCardHeader>
<CCardBody>
<CChartLine
:data="chartData"
:options="chartOptions"
style="height: 300px"
/>
</CCardBody>
</CCard>
</template>
<script setup>
import { CChartLine } from '@coreui/vue-chartjs'
const chartData = {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [
{
label: 'Sales 2024',
backgroundColor: 'rgba(220, 53, 69, 0.1)',
borderColor: 'rgba(220, 53, 69, 1)',
data: [40, 20, 12, 39, 10, 40, 39],
},
],
}
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
},
},
}
</script>
```
### Chart Types
CoreUI provides Vue wrappers for Chart.js:
- `CChartLine` - Line charts
- `CChartBar` - Bar charts
- `CChartDoughnut` - Doughnut charts
- `CChartPie` - Pie charts
- `CChartPolarArea` - Polar area charts
- `CChartRadar` - Radar charts
## Code Quality
### ESLint Configuration
The project uses ESLint with Vue and Prettier plugins:
```bash
# Check for issues
npm run lint
# Auto-fix issues (when possible)
npm run lint -- --fix
```
### Code Style Guidelines
**JavaScript**:
- No semicolons (enforced by Prettier)
- Single quotes for strings
- 2-space indentation
- Arrow functions preferred
- Destructuring when possible
**Vue**:
- Composition API with script setup
- Props defined with defineProps()
- Meaningful component names
- Scoped styles
**File naming**:
- PascalCase for components: `UserCard.vue`
- camelCase for utilities: `dateHelper.js`
- kebab-case for styles: `user-card.scss`
### Pre-commit Checks
**Recommended**: Set up pre-commit hooks with Husky:
```bash
npm install --save-dev husky lint-staged
# Add to package.json
{
"lint-staged": {
"src/**/*.{js,vue}": ["eslint --fix", "prettier --write"]
}
}
```
## Testing
### Manual Testing Checklist
Before committing changes:
- [ ] Test in both light and dark themes
- [ ] Test responsive design (mobile, tablet, desktop)
- [ ] Check browser console for errors
- [ ] Verify all links and navigation work
- [ ] Test form validation and submission
- [ ] Check accessibility (keyboard navigation, screen readers)
### Browser Testing
Test in modern browsers:
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
### Responsive Testing
Test at common breakpoints:
- Mobile: 375px, 414px
- Tablet: 768px, 1024px
- Desktop: 1366px, 1920px
**Tip**: Use Chrome DevTools device toolbar (Cmd/Ctrl + Shift + M)
## Build and Deployment
### Production Build
Create optimized production build:
```bash
npm run build
```
Output in `dist/` directory:
- Minified JavaScript bundles
- Extracted and minified CSS
- Optimized assets
- Source maps
### Build Analysis
Check bundle size:
```bash
npm run build
# Output shows:
# - Total bundle size
# - Individual chunk sizes
# - Asset sizes
```
### Preview Production Build
Test production build locally:
```bash
npm run preview
```
Opens preview server at `http://localhost:4173`
### Deployment Platforms
**Static hosting** (builds to static files):
1. **Netlify**:
- Connect GitHub repository
- Build command: `npm run build`
- Publish directory: `dist`
2. **Vercel**:
- Import Git repository
- Framework preset: Vite
- Build command: `npm run build`
3. **GitHub Pages**:
- Build locally: `npm run build`
- Push `dist/` folder to `gh-pages` branch
4. **AWS S3 + CloudFront**:
- Upload `dist/` contents to S3 bucket
- Configure CloudFront distribution
### Environment Variables
Create `.env` file (not committed to Git):
```bash
VITE_API_URL=https://api.example.com
VITE_APP_NAME=My App
```
**Usage in code**:
```javascript
const apiUrl = import.meta.env.VITE_API_URL
```
**IMPORTANT**: Only variables prefixed with `VITE_` are exposed to the app.
## Troubleshooting
### Common Issues
**Problem**: Port 3000 already in use
**Solution**:
```bash
# Kill process on port 3000
# Mac/Linux:
lsof -ti:3000 | xargs kill
# Windows:
netstat -ano | findstr :3000
taskkill /PID <PID> /F
# Or change port in vite.config.mjs
```
---
**Problem**: Module not found errors
**Solution**:
```bash
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install
```
---
**Problem**: Styles not updating
**Solution**:
- Clear browser cache
- Hard refresh (Cmd/Ctrl + Shift + R)
- Restart dev server
---
**Problem**: HMR not working
**Solution**:
- Check file is saved
- Restart dev server
- Check for syntax errors in console
---
**Problem**: Build fails with memory error
**Solution**:
```bash
# Increase Node memory limit
NODE_OPTIONS="--max-old-space-size=4096" npm run build
```
### Debugging Tips
**Vue DevTools**:
- Inspect component hierarchy
- View props and state
- Profile component renders
- Inspect Pinia stores
**Console logging**:
```javascript
console.log('Variable:', variable)
console.table(arrayOfObjects)
console.error('Error:', error)
```
## Best Practices
### Performance
1. **Lazy load routes**: Use dynamic imports for code splitting
2. **Use computed**: For derived values instead of methods
3. **Optimize re-renders**: Use v-memo for expensive renders
4. **Virtualize long lists**: Use libraries like vue-virtual-scroller
5. **Optimize images**: Use WebP format, lazy loading
### Accessibility
1. **Semantic HTML**: Use proper heading hierarchy (h1-h6)
2. **ARIA labels**: Add aria-label for icon buttons
3. **Keyboard navigation**: Ensure all interactive elements are keyboard-accessible
4. **Color contrast**: Meet WCAG AA standards (4.5:1 for text)
5. **Form labels**: Associate all form inputs with labels
### Security
1. **Validate input**: Sanitize user input before rendering
2. **Use HTTPS**: Always serve over HTTPS in production
3. **Content Security Policy**: Configure CSP headers
4. **Dependency audits**: Run `npm audit` regularly
5. **Environment variables**: Never commit secrets to Git
### Code Organization
1. **Single Responsibility**: One component does one thing well
2. **DRY Principle**: Don't Repeat Yourself - extract reusable code
3. **Consistent naming**: Follow naming conventions throughout
4. **File organization**: Group related files together
5. **Documentation**: Comment complex logic and add JSDoc
### Git Workflow
**Commit messages** (Conventional Commits):
```
feat: add user profile page
fix: resolve navigation bug on mobile
docs: update README with deployment instructions
style: format code with Prettier
refactor: extract form validation logic
test: add tests for UserCard component
chore: update dependencies
```
**Branch naming**:
```
feature/user-profile
fix/navigation-bug
refactor/form-validation
docs/deployment-guide
```
---
This guide covers the essential workflows and patterns for developing with the CoreUI Free Vue Admin Template. For additional questions, consult the [CoreUI Vue Documentation](https://coreui.io/vue/docs/) or the [Vue 3 Documentation](https://vuejs.org/).
Happy coding! 🚀