7.3 KiB
myCRM - AI Agent Instructions
Project Overview
Modern, modular CRM system built with Symfony LTS. Focus on security, UX, and extensibility with a native-app-like feel through heavy AJAX usage.
Tech Stack
- Backend: Symfony (current LTS version) - PHP framework following best practices
- Database: MariaDB (unless specific reasons dictate otherwise)
- Frontend: Vue.js 3 with Composition API, bundled via Symfony Webpack Encore
- UI Components: PrimeVue (DataTable, Charts, Forms, Dialogs for professional CRM UI)
- Authentication: Symfony Security component with modern permission system (RBAC/Voter pattern)
- API: API Platform for RESTful APIs with auto-generated OpenAPI docs
- Admin UI: Custom Vue.js components (no EasyAdmin) for maximum flexibility
Development Workflow
# Initial setup
composer install
php bin/console doctrine:database:create
php bin/console doctrine:migrations:migrate
npm install && npm run dev
# Run development (parallel terminals recommended)
symfony serve -d # Backend server on :8000
npm run watch # Encore: Hot reload for Vue.js changes
# Production build
npm run build # Minified assets for deployment
# Run tests
php bin/phpunit # Backend tests
npm run test:unit # Vue component tests (Vitest/Jest)
php bin/console doctrine:schema:validate
# Cache management
php bin/console cache:clear
APP_ENV=prod php bin/console cache:warmup
Symfony-Specific Conventions
Directory Structure (Symfony Standard)
/config - YAML/PHP configuration files, routes
/src
/Controller - HTTP controllers (keep thin, delegate to services)
/Entity - Doctrine entities (CRM: Contact, Company, Deal, Activity, User)
/Repository - Database queries
/Service - Business logic (pipeline calculations, lifecycle management)
/Security/Voter - Permission logic per entity
/Form - Form types for entities
/EventListener - Doctrine events, kernel events
/templates - Twig templates (base layout, embed Vue app)
/assets
/js - Vue.js components, composables, stores (Pinia)
/components - Reusable Vue components (ContactCard, DealPipeline)
/views - Page-level Vue components
/api - API client wrappers for API Platform endpoints
/styles - SCSS/CSS (scoped styles in Vue SFCs)
/migrations - Doctrine migrations (version controlled)
/tests - PHPUnit tests (backend), Vitest/Jest (frontend)
Key Architectural Patterns
Controllers: Keep lean - validate input, call services, return JSON/HTML
// Good: Delegate to service
return $this->json($contactService->createContact($request->toArray()));
Services: Inject dependencies via constructor, use interfaces for flexibility
class ContactLifecycleService {
public function __construct(
private EntityManagerInterface $em,
private EventDispatcherInterface $dispatcher
) {}
}
Entities: Use Doctrine annotations/attributes, define relationships carefully
- Contact ↔ Company (ManyToOne/OneToMany)
- Contact ↔ Activities (OneToMany)
- Deal ↔ Contact (ManyToOne with Deal ownership)
Security Voters: Implement granular permissions per entity action
// Example: ContactVoter checks if user can VIEW/EDIT/DELETE specific contact
protected function supports(string $attribute, mixed $subject): bool
Vue.js Integration: Symfony renders base Twig template, Vue takes over
- Twig template loads Vue app entry point via Encore
- API Platform provides REST endpoints, Vue consumes them
- State management: Pinia stores for global state (current user, permissions)
- Routing: Vue Router for SPA navigation within CRM modules
API Pattern: API Platform handles CRUD, custom endpoints for business logic
// Custom API endpoint example
#[Route('/api/deals/{id}/advance-stage', methods: ['POST'])]
public function advanceStage(Deal $deal): JsonResponse
{
$this->denyAccessUnlessGranted('EDIT', $deal);
return $this->json($this->dealService->advanceToNextStage($deal));
}
Vue Component Pattern: Composables for API calls, components for UI
// composables/useContacts.js
export function useContacts() {
const contacts = ref([])
const loading = ref(false)
async function fetchContacts() {
loading.value = true
const response = await fetch('/api/contacts')
contacts.value = await response.json()
loading.value = false
}
return { contacts, loading, fetchContacts }
}
CRM Domain Logic
Core Entities:
Contact: Person with lifecycle state (Lead → Qualified → Customer)Company: Organization linked to contactsDeal: Sales opportunity with pipeline stage, value, probabilityActivity: Interaction record (call, email, meeting, note)User: System user with role-based permissions
Permission System: Use Symfony Voters for fine-grained access
- Entity-level: Can user view/edit this specific contact?
- Module-level: Can user access Reports module?
- Action-level: Can user export data?
API Modules: Expose selected functionality via RESTful endpoints
- Authentication: JWT tokens or API keys
- Rate limiting: Consider API Platform's built-in support
- Documentation: OpenAPI/Swagger auto-generated
Code Quality Standards
- Follow Symfony best practices and PSR-12
- Type hints everywhere (PHP 8.x features)
- Doctrine migrations for all schema changes (never alter DB manually)
- Services autowired and autoconfigured in
services.yaml - Environment variables for configuration (
.env,.env.local)
Testing Strategy
- Unit tests for services (PHPUnit)
- Functional tests for controllers (WebTestCase)
- Doctrine schema validation in CI
- Security: Test voter logic explicitly
Frontend Architecture Details
Encore Configuration: webpack.config.js compiles Vue SFCs
Encore
.addEntry('app', './assets/js/app.js') // Main Vue app
.enableVueLoader()
.enableSassLoader()
.enablePostCssLoader()
PrimeVue Integration:
- Install:
npm install primevue primeicons - Use DataTable for contact/deal lists with filtering, sorting, pagination
- Use Dialog/Sidebar for forms (better UX than full page forms)
- Use Chart components for pipeline analytics, revenue forecasts
- Theme: Customize PrimeVue theme to match brand (Sass variables)
Vue Component Organization:
ContactList.vue- PrimeVue DataTable with filters, export (talks to/api/contacts)ContactDetail.vue- TabView with form, activity timeline, related dealsDealPipeline.vue- Custom Kanban or PrimeVue OrderList (update via API Platform)ActivityFeed.vue- Timeline component with real-time updatesDashboard.vue- Chart.js via PrimeVue Chart for KPIs
Authentication in Vue: Pass Symfony user data to Vue via Twig
<div id="app"
data-user="{{ app.user|json_encode }}"
data-permissions="{{ user_permissions|json_encode }}">
</div>
Next Steps for AI Agents
As code develops, update this file with:
- PrimeVue theme customization (specific color palette, component overrides)
- Custom Doctrine types or extensions in use
- Mercure integration for real-time updates (if implemented)
- Event-driven patterns (custom events for CRM workflows)
- Background job processing with Symfony Messenger
- Deployment strategy (Docker, traditional hosting)