## Why Cursor Rules Matter for Angular, Ionic, and Firebase/Firestore Stacks
When developing full-featured mobile and web applications using Angular as the frontend framework, Ionic for hybrid mobile capabilities, and Firebase/Firestore for backend services, maintaining consistency is crucial. Cursor, the AI-powered code editor, shines when guided by specific rules. These rules act as a blueprint, ensuring that AI-generated code aligns perfectly with your project's architecture, naming conventions, and best practices. By defining these upfront in a `.cursorrules` file, you empower Cursor to produce high-quality, production-ready code instantly.
This guide provides a complete set of rules optimized for this tech stack. Implementing them reduces debugging time, enforces scalability, and accelerates development cycles. For a ready-to-use template, explore the [official Cursor Rules repo for Angular-Ionic-Firebase](https://github.com/ionicthemes/cursor-rules-angular-ionic-firebase).
## Defining Project Structure
A well-organized project structure is the foundation of any successful Angular-Ionic app. Cursor rules enforce a strict hierarchy to prevent sprawl and make navigation intuitive.
### Core Folders
- **src/app/core**: Houses global services, interceptors, guards, and utilities shared across the app.
- **src/app/shared**: Contains reusable components, directives, pipes, and modules.
- **src/app/features**: Feature modules with lazy-loaded pages, components, and services specific to app sections (e.g., `auth`, `dashboard`).
- **src/app/pages**: Ionic-specific page components, each in its own folder with `.page.ts`, `.page.html`, `.page.scss`, and `.page.module.ts`.
**Real-World Example**: For an e-commerce app, structure `src/app/features/products` with `products.module.ts`, `products-routing.module.ts`, and sub-components like `product-list` and `product-detail`.
```
// Enforced folder structure in .cursorrules
src/
app/
core/
services/
guards/
interceptors/
shared/
components/
pipes/
features/
auth/
auth.module.ts
+state/
dashboard/
pages/
home/
home.page.ts
home.page.html
...
```
This setup supports Angular's standalone components (v17+) while maintaining Ionic's page paradigm, enabling seamless lazy loading and code splitting for better performance in mobile apps.
## Strict Naming Conventions
Consistent naming prevents confusion in large teams or long-term maintenance. Cursor rules mandate camelCase for files, PascalCase for classes, and kebab-case for selectors.
### Key Rules
- **Components/Services**: `user-profile.component.ts`, `auth.service.ts`
- **Interfaces**: `user.interface.ts`
- **Modules**: `feature.module.ts`
- **SCSS Files**: Match component names, e.g., `user-profile.component.scss`
- **Firestore Collections**: Plural, lowercase with hyphens, e.g., `users`, `user-orders`
**Practical Tip**: In Ionic, page selectors use `app-page-name`, ensuring CSS isolation.
```
// Example component naming
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.scss']
})
export class UserProfileComponent { ... }
```
Adding context: These conventions align with Angular CLI schematics and Ionic generators, making `ng generate` outputs instantly compliant.
## Component Architecture Best Practices
Leverage Angular's modern standalone components while respecting Ionic's page structure.
### Standalone by Default
- All new components, directives, pipes: Standalone.
- Import only necessary dependencies; no heavy shared modules.
### Ionic Pages
- Each page: Full folder with four files (TS, HTML, SCSS, Module).
- Use `ion-page`, `ion-header`, `ion-content` wrappers.
**Scenario**: Building a login page.
```
// login.page.ts
@IonicPage() // Custom decorator if needed
@Component({
selector: 'app-login',
standalone: true,
imports: [IonicModule, FormsModule, ReactiveFormsModule],
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss']
})
export class LoginPage {
loginForm = this.fb.group({ email: ['', [Validators.required, Validators.email]], password: ['', Validators.required] });
constructor(private fb: FormBuilder, private authService: AuthService) {}
onSubmit() { this.authService.login(this.loginForm.value); }
}
```
This reduces bundle size by 20-30% compared to NgModules, ideal for Ionic PWAs and apps.
## State Management with NgRx
For complex apps, enforce NgRx for predictable state.
### Structure
- **+state/** folder per feature: `actions.ts`, `effects.ts`, `reducer.ts`, `selectors.ts`, `state.module.ts`.
- Global state in `src/app/core/+state`.
**Example: User Feature State**
```
// user.actions.ts
export const loadUser = createAction('[User] Load User', props<{ id: string }>());
// user.reducer.ts
const userReducer = createReducer(
initialState,
on(loadUser, (state, { id }) => ({ ...state, loading: true })),
// ...
);
```
Cursor auto-generates facades and effects, ensuring immutability and side-effect isolation.
## Firebase and Firestore Integration
Seamlessly connect with Firebase services using AngularFire.
### Services
- Dedicated services: `firestore.service.ts`, `auth.service.ts`, `storage.service.ts`.
### Collection Rules
- Collections: `users/{userId}/orders/{orderId}` for subcollections.
- Queries: Use `startAfter`, `limit` for pagination.
**Code Snippet: Firestore Service**
```
import { Firestore, collection, query, where, getDocs } from '@angular/fire/firestore';
@Injectable({ providedIn: 'root' })
export class ProductsService {
constructor(private firestore: Firestore) {}
async getProducts(category: string): Promise<Product[]> {
const q = query(collection(this.firestore, 'products'), where('category', '==', category), limit(20));
const snapshot = await getDocs(q);
return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() } as Product));
}
}
```
**Added Value**: Always handle errors with RxJS `catchError` and offline support via Firestore's persistence.
## Ionic-Specific Guidelines
Optimize for Capacitor and mobile deployment.
- **Components**: Prefer Ionic's `ion-*` over custom HTML.
- **Routing**: Deep links with `app-routing.module.ts` using Ionic's `redirectTo`.
- **Themes**: Variables in `global.scss`, dark mode support.
**Example: Responsive Toolbar**
```
<!-- home.page.html -->
<ion-header>
<ion-toolbar>
<ion-title>Home</ion-title>
<ion-buttons slot="end">
<ion-button (click)="openMenu()">Menu</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
```
## Testing and CI/CD
Enforce 80% coverage.
- **Unit Tests**: Jest + ng-mocks for components/services.
- **E2E**: Cypress for Ionic flows.
```
// user.service.spec.ts
describe('UserService', () => {
let service: UserService;
let firestoreMock: jasmine.SpyObj<Firestore>;
beforeEach(() => {
firestoreMock = jasmine.createSpyObj('Firestore', ['collection']);
service = new UserService(firestoreMock as any);
});
it('should fetch user', async () => {
// Mock and assert
});
});
```
## Deployment Checklist
- Build: `ionic build --prod`
- Firebase Hosting: `firebase deploy`
- Capacitor: `npx cap sync && npx cap open android/ios`
By following these rules, your Cursor-assisted development becomes a powerhouse for rapid prototyping to production apps. Customize the `.cursorrules` file as needed, and always commit it to version control for team consistency.
<div style="text-align: center; margin-top: 2rem;">
<a href="https://cursor.directory/angular-ionic-firebase-firestore-cursor-rules" target="_blank" rel="noopener noreferrer" class="view-full-resource-btn" style="display: inline-block; background-color: #f97316; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background-color 0.2s;">View Full Resource</a>
</div>