Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 92 additions & 39 deletions frontend/angular/data-forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,20 @@ last_updated: 2026-03-22
> [!NOTE]
> **Context:** Form Safety
### ❌ Bad Practice
`[(ngModel)]` without strict model typing.
```html
<input [(ngModel)]="userAge">
```
### ⚠️ Problem
Risk of assigning a string to a numeric field.
Using `[(ngModel)]` without strict model typing risks assigning a string to a numeric field or vice versa, causing runtime errors and confusing data flow.
### ✅ Best Practice
Use Reactive Forms with `FormControl<string>` typing or new Signal-based Forms (when out of developer preview).


```typescript
userAge = model<number>(0);
```
```html
<input type="number" [(ngModel)]="userAge">
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
Use Signal-based `model()` inputs combined with strict HTML input types. This provides a deterministic, type-safe implementation that maintains strict architectural boundaries.
## ⚡ 47. Untyped `FormGroup`
> [!NOTE]
> **Context:** Reactive Forms
Expand Down Expand Up @@ -70,56 +75,87 @@ Use Flattening Operators (`switchMap`, `concatMap`, `mergeMap`).
> [!NOTE]
> **Context:** Network Efficiency
### ❌ Bad Practice
Ignoring request cancellation when navigating away from the page.
```typescript
fetchData() {
this.http.get('/api/data').subscribe(data => this.data.set(data));
}
```
### ⚠️ Problem
Requests continue hanging, consuming traffic.
Ignoring request cancellation when navigating away from the page or making subsequent requests leads to hanging connections, memory leaks, and potential race conditions if old requests resolve after new ones.
### ✅ Best Practice
HttpClient automatically supports cancellation upon unsubscription. With signals: ensure `rxResource` or the effect correctly cancels the request.


```typescript
fetchData() {
this.http.get('/api/data').pipe(takeUntilDestroyed()).subscribe(data => this.data.set(data));
}
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
Always tie HTTP requests to the component lifecycle using `takeUntilDestroyed()`. This automatically aborts pending requests when the context is destroyed, optimizing network efficiency and ensuring deterministic state.
## ⚡ 50. Mutating Inputs directly
> [!NOTE]
> **Context:** Unidirectional Data Flow
### ❌ Bad Practice
```typescript
this.inputData.push(newItem);
data = input<Item[]>([]);
addItem(newItem: Item) {
this.data().push(newItem);
}
```
### ⚠️ Problem
The parent component remains unaware of the change. Violates the One-Way Data Flow principle.
Directly mutating an array or object received via input bypasses the reactivity system and violates the One-Way Data Flow principle. The parent component remains unaware of the change.
### ✅ Best Practice
Emit event (`output`) upwards; the parent changes the data and passes the new object downwards.

```typescript
data = input<Item[]>([]);
dataChange = output<Item[]>();

addItem(newItem: Item) {
this.dataChange.emit([...this.data(), newItem]);
}
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
Emit an event using the `output()` API upwards; the parent handles the mutation immutably and passes the new reference downwards. This maintains unidirectional data flow and ensures correct change detection.
## ⚡ 51. `ngModel` inside Reactive Form
> [!NOTE]
> **Context:** Form Mixing
### ❌ Bad Practice
Using `formControlName` and `[(ngModel)]` on the same input.
```html
<form [formGroup]="form">
<input formControlName="name" [(ngModel)]="localName">
</form>
```
### ⚠️ Problem
Deprecated behavior. Causes form and model synchronization conflicts.
Mixing `formControlName` and `[(ngModel)]` is deprecated behavior. It creates two sources of truth, causing form and model synchronization conflicts and unpredictable value updates.
### ✅ Best Practice
Use only one approach: either Reactive or Template-driven.


```html
<form [formGroup]="form">
<input formControlName="name">
</form>
```
```typescript
// Subscribe to value changes in component if needed
nameValue = toSignal(this.form.get('name').valueChanges);
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
Use only one approach strictly: Reactive Forms with `formControlName`. For reactivity, derive a signal from `valueChanges` using `toSignal()` instead of relying on two-way binding.
## ⚡ 52. Complex Validators in Template
> [!NOTE]
> **Context:** Form Logic
### ❌ Bad Practice
Validation via HTML attributes for complex logic.
```html
<input pattern="^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$" required>
```
### ⚠️ Problem
Hard to test, no reusability.
Placing complex regex validations directly in HTML attributes creates code that is impossible to unit test independently, provides poor error messages, and lacks reusability.
### ✅ Best Practice
Custom Validator Functions or Async Validators in the component class.

```typescript
const passwordValidator: ValidatorFn = (control: AbstractControl) => {
const valid = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/.test(control.value);
return valid ? null : { invalidPassword: true };
};

password = new FormControl('', [Validators.required, passwordValidator]);
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
Abstract complex logic into Custom Validator Functions within the TypeScript class. This ensures high testability, strong typing, and reusability across multiple forms.
## ⚡ 53. Forgetting `updateOn: 'blur'`
> [!NOTE]
> **Context:** Performance
Expand All @@ -137,26 +173,43 @@ Trigger validation/update only when the user has finished typing.
> [!NOTE]
> **Context:** UX
### ❌ Bad Practice
`.subscribe(data => ...)` without an error callback.
```typescript
this.http.get<User>('/api/user').subscribe(data => {
this.user.set(data);
});
```
### ⚠️ Problem
On a 500 error, the application "hangs" in a loading state.
Failing to handle errors leads to silent failures or unhandled exceptions in the console. On a 500 error, the application may "hang" in an infinite loading state, destroying the UX.
### ✅ Best Practice
Global Error Handler or `catchError` in the pipe returning a safe value.


```typescript
this.http.get<User>('/api/user').pipe(
catchError(err => {
this.toastService.error('Failed to load user');
return of(null);
})
).subscribe(data => {
if (data) this.user.set(data);
});
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
Always implement a `catchError` block in the RxJS pipe to handle API failures gracefully. Return a safe fallback value and notify the user to ensure deterministic application flow.
## ⚡ 55. Hardcoded API URLs
> [!NOTE]
> **Context:** Maintainability
### ❌ Bad Practice
`http.get('https://api.com/users')`
```typescript
this.http.get('https://api.production.com/users');
```
### ⚠️ Problem
Inability to switch environments (dev/prod).
Hardcoding API URLs directly into service methods completely couples the code to a specific environment, making it impossible to seamlessly deploy to staging or local dev environments without manual changes.
### ✅ Best Practice
Using InjectionToken `API_URL` and environment configuration.

```typescript
export const API_URL = new InjectionToken<string>('API_URL');

// In service:
private apiUrl = inject(API_URL);
this.http.get(`${this.apiUrl}/users`);
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
Utilize an `InjectionToken` combined with environment configurations to provide the API URL. This ensures configuration is decoupled from business logic and allows deterministic dependency injection.
---
51 changes: 40 additions & 11 deletions frontend/angular/expert-niche.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,57 @@ Always initialize signals with the full object shape (even with null) to preserv
> [!NOTE]
> **Context:** Reactivity Theory
### ❌ Bad Practice
Relying on `effect` to fire synchronously.
```typescript
count = signal(0);
doubleCount = signal(0);

constructor() {
effect(() => {
this.doubleCount.set(this.count() * 2);
});
}
```
### ⚠️ Problem
Signals guarantee "Glitch Freedom" (absence of intermediate inconsistent states), but effects are asynchronous (microtask timing).
Using `effect` to derive or synchronize local state is an anti-pattern. Effects are asynchronous (microtask timing), which means the state can momentarily be inconsistent ("glitch") before the effect runs, leading to UI flicker or bugs.
### ✅ Best Practice
Do not use effects to synchronize local state. Use `computed`.


```typescript
count = signal(0);
doubleCount = computed(() => this.count() * 2);
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
Use `computed` for derived state. Computed signals evaluate lazily and synchronously when read, ensuring true Glitch Freedom and eliminating unnecessary change detection cycles.
## ⚡ 59. Memory leaks in `root` Effects
> [!NOTE]
> **Context:** Application Lifecycle
### ❌ Bad Practice
Creating an effect in a service without `manualCleanup`.
```typescript
@Injectable({ providedIn: 'root' })
export class GlobalService {
constructor() {
effect(() => {
// Listens to global events indefinitely
console.log('State changed', this.state());
});
}
}
```
### ⚠️ Problem
Effects in `root` services live forever. If they subscribe to something global, it can leak.
Effects created in `root` services live for the entire lifecycle of the application. If the service relies on dynamic instantiation or lazy loading and is later destroyed, the effect will continue to execute, causing memory leaks and unexpected behavior.
### ✅ Best Practice
Usually fine, but if the service is destroyed (rare lazy loading case), the effect must be cleaned up with `effectRef.destroy()`.

```typescript
@Injectable({ providedIn: 'root' })
export class GlobalService implements OnDestroy {
private effectRef = effect(() => {
console.log('State changed', this.state());
}, { manualCleanup: true });

ngOnDestroy() {
this.effectRef.destroy();
}
}
```
### 🚀 Solution
This approach provides a deterministic, type-safe implementation that is resilient and Agent-Readable, maintaining strict architectural boundaries.
When creating effects in long-lived or dynamic services, explicitly configure them with `{ manualCleanup: true }` and destroy the reference during the service's `ngOnDestroy` lifecycle hook. This ensures deterministic resource management.
## 📖 60. `runInInjectionContext`
> [!NOTE]
> **Context:** Advanced DI
Expand Down
29 changes: 18 additions & 11 deletions frontend/javascript/modern-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,24 +151,31 @@ Treat objects as immutable. Use the spread operator to create copies with update
> **Context:** Simplifying conditional branching.
### ❌ Bad Practice
```javascript
switch (action) {
case 'CREATE': return doCreate();
case 'UPDATE': return doUpdate();
default: return doNothing();
function executeAction(action) {
switch (action) {
case 'CREATE':
return doCreate();
case 'UPDATE':
return doUpdate();
default:
return doNothing();
}
}
```
### ⚠️ Problem
`switch` statements are verbose, require `break` to prevent fallthrough bugs, and have a non-standard block scope.
`switch` statements are verbose, require `break` to prevent fallthrough bugs if not returning immediately, and have a non-standard block scope. They also violate the Open/Closed Principle making it harder to extend dynamically.
### ✅ Best Practice
```javascript
const actions = {
CREATE: doCreate,
UPDATE: doUpdate
};
return (actions[action] || doNothing)();
function executeAction(action) {
const actions = {
CREATE: doCreate,
UPDATE: doUpdate
};
return (actions[action] || doNothing)();
}
```
### 🚀 Solution
Use an Object Literal (or Map) as a lookup table. It is cleaner, faster, and more extensible.
Use an Object Literal (or Map) as a lookup table. It provides a deterministic, type-safe execution path that is cleaner, faster, and allows for dynamic extension without modifying the core logic.
## ⚡ 19. Not using Optional Chaining `?.`
> [!NOTE]
> **Context:** Safe property access in nested objects.
Expand Down
2 changes: 1 addition & 1 deletion frontend/qwik/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ last_updated: 2026-03-22

## ⚡ II. Advanced Performance

## 1. Synchronous Closures
## 🚨 1. Synchronous Closures
> [!NOTE]
> **Context:** Component Event Handlers
### ❌ Bad Practice
Expand Down
2 changes: 1 addition & 1 deletion frontend/qwik/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ last_updated: 2026-03-22
- Adhere to the defined [Architectural Patterns](../../architectures/readme.md) when building applications.
- Strongly prefer **Feature Sliced Design (FSD)** for applications scaling across multiple teams.
## 🚀 I. Basics & Popular
## 1. Passing Closures as Props
## 🚨 1. Passing Closures as Props
> [!NOTE]
> **Context:** Component Props
### ❌ Bad Practice
Expand Down
2 changes: 1 addition & 1 deletion frontend/qwik/state-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ last_updated: 2026-03-22

## ⚡ II. State Management

## 1. Storing Unserializable Data
## 🚨 1. Storing Unserializable Data
> [!NOTE]
> **Context:** Reactive Stores and State Object
### ❌ Bad Practice
Expand Down
12 changes: 4 additions & 8 deletions frontend/react/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ last_updated: 2026-03-22
- **Tech Stack Version:** React 19+
## 📚 Topics

### 🔹 1. Manual Memoization vs React Compiler
### 🚨 1. Manual Memoization vs React Compiler
> [!NOTE]
> **Context:** Avoiding unnecessary re-renders.
### ❌ Bad Practice
Expand Down Expand Up @@ -51,11 +51,9 @@ function UserList({ users }) {
}
```
### 🚀 Solution
Rely on the **React Compiler** (introduced in React 19+). The compiler automatically memoizes values and functions, meaning manual hooks are largely obsolete and code becomes purely declarative.
- **Performance Note:** The React Compiler analyzes your component structure and injects optimal memoization (similar to SolidJS's granular updates), eliminating the overhead of manual dependency tracking.
- **Security Note:** While the React Compiler does not directly impact security, it ensures components render exactly when their inputs change, reducing side effects that might otherwise expose temporary or stale data to users.
Rely on the **React Compiler** (introduced in React 19+). The compiler automatically memoizes values and functions, meaning manual hooks are largely obsolete and code becomes purely declarative. This optimizes components structurally and removes manual dependency tracking overhead.

### 🔹 2. Resolving Promises During Render
### 🚨 2. Resolving Promises During Render
> [!NOTE]
> **Context:** Conditionally handling promises without `useEffect` or `useState`.
### ❌ Bad Practice
Expand Down Expand Up @@ -90,8 +88,6 @@ function Profile({ profilePromise }) {
// </Suspense>
```
### 🚀 Solution
Use the `use()` API inside components combined with `<Suspense>`.
- **Performance Note:** `use()` suspends the component rendering if the promise is not resolved. This seamlessly integrates with `<Suspense>`, providing a highly optimized rendering fallback behavior.
- **Security Note:** `use()` can also resolve context, mitigating prop-drilling vulnerabilities and ensuring components securely consume data directly from contexts they are explicitly authorized for. Always sanitize any text coming from external APIs before rendering.
Use the `use()` API inside components combined with `<Suspense>`. `use()` suspends the component rendering if the promise is not resolved. This seamlessly integrates with `<Suspense>`, providing a highly optimized rendering fallback behavior and ensuring safe resolution of asynchronous data.

[⬆️ Back to Top](#)
Loading
Loading