Skip to content
Back to skills

058 Architecture Patterns C9e7d0c0

ASecurity

Prioritize native JavaScript, HTML, and Web APIs over external dependencies. This approach delivers: - Smaller bundle sizes - Better performance - Reduced maintenance burden - Future-proof code that doesn't depend on library churn

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
testingjavascripttypescriptgojavareacttestingdebuggingapisecurityperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 058-architecture-patterns_c9e7d0c0 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 058 Architecture Patterns C9e7d0c0?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 058 Architecture Patterns C9e7d0c0
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-058-architecture-patterns-c9e7d0c0/badge)](https://www.skillsdirectory.com/skills/tools-only-058-architecture-patterns-c9e7d0c0)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Architecture Patterns & Best Practices

## Native-First Development Philosophy

Prioritize native JavaScript, HTML, and Web APIs over external dependencies. This approach delivers:
- Smaller bundle sizes
- Better performance
- Reduced maintenance burden
- Future-proof code that doesn't depend on library churn

### Decision Framework for Dependencies

Before adding any external package, verify:

1. **Native APIs cannot accomplish this** - Check MDN and Can I Use
2. **Preact built-ins are insufficient** - signals, hooks, Context API
3. **Bundle size cost is justified** - Measure the actual benefit gained

## Zero-Build Architecture

For prototypes, demos, and small applications, use:
- ES modules via CDN (esm.sh)
- Import maps for dependency management
- HTM for zero-transpilation JSX-like syntax
- Inline or linked CSS (Tailwind via CDN)

### When to Introduce Build Tools

Consider build tooling when:
- TypeScript is required for team collaboration
- Code splitting across multiple entry points is needed
- CSS preprocessing (beyond Tailwind) is essential
- Bundle optimization for production is critical

## State Management Patterns

### Local Component State

Use for isolated component logic:

```javascript
import { useSignal } from '@preact/signals';

function Counter() {
  const count = useSignal(0);
  return html`
    <button onClick=${() => count.value++}>
      Count: ${count}
    </button>
  `;
}
```

### Global Signals

Use for shared state across components:

```javascript
// state.js
import { signal } from '@preact/signals';

export const currentUser = signal(null);
export const isAuthenticated = signal(false);

// Any component can import and use
import { currentUser } from './state.js';
```

### Context API

Use for dependency injection and theme/config:

```javascript
import { createContext } from 'preact';
import { useContext } from 'preact/hooks';

const ApiContext = createContext(null);

function App() {
  const api = createApiClient();
  return html`
    <${ApiContext.Provider} value=${api}>
      <${MainApp} />
    </${ApiContext.Provider}>
  `;
}
```

### External State Libraries

Consider Zustand or Jotai only when:
- Complex state derivations are needed
- Dev tools and time-travel debugging are required
- Team has existing patterns with these libraries

## Data Fetching Patterns

### Simple Fetch with Hooks

```javascript
import { useSignal, useSignalEffect } from '@preact/signals';

function UserProfile({ userId }) {
  const user = useSignal(null);
  const loading = useSignal(true);
  const error = useSignal(null);

  useSignalEffect(() => {
    loading.value = true;
    fetch(`/api/users/${userId}`)
      .then(r => r.json())
      .then(data => {
        user.value = data;
        loading.value = false;
      })
      .catch(err => {
        error.value = err;
        loading.value = false;
      });
  });

  if (loading.value) return html`<div>Loading...</div>`;
  if (error.value) return html`<div>Error: ${error.value.message}</div>`;
  return html`<div>${user.value.name}</div>`;
}
```

### Suspense for Async Data

```javascript
import { Suspense, lazy } from 'preact/compat';

// Resource pattern
function wrapPromise(promise) {
  let status = 'pending';
  let result;
  const suspender = promise.then(
    r => {
      status = 'success';
      result = r;
    },
    e => {
      status = 'error';
      result = e;
    }
  );
  return {
    read() {
      if (status === 'pending') throw suspender;
      if (status === 'error') throw result;
      return result;
    }
  };
}

const userResource = wrapPromise(fetch('/api/user').then(r => r.json()));

function UserData() {
  const user = userResource.read();
  return html`<div>${user.name}</div>`;
}

function App() {
  return html`
    <${Suspense} fallback=${html`<div>Loading...</div>`}>
      <${UserData} />
    </${Suspense}>
  `;
}
```

## Routing Strategies

### Hash-based Routing (Simplest)

```javascript
import { useSignal, useSignalEffect } from '@preact/signals';

const currentRoute = signal(window.location.hash.slice(1) || '/');

window.addEventListener('hashchange', () => {
  currentRoute.value = window.location.hash.slice(1) || '/';
});

function App() {
  return html`
    <nav>
      <a href="#/">Home</a>
      <a href="#/about">About</a>
    </nav>
    ${currentRoute.value === '/' && html`<${HomePage} />`}
    ${currentRoute.value === '/about' && html`<${AboutPage} />`}
  `;
}
```

### History API Routing (Production)

Consider preact-router or wouter for:
- Clean URLs without hashes
- Server-side rendering requirements
- Nested route patterns

## Form Handling

### Native Form Validation

Leverage HTML5 validation before JavaScript:

```javascript
function SignupForm() {
  const handleSubmit = (e) => {
    e.preventDefault();
    if (!e.target.checkValidity()) return;
    
    const formData = new FormData(e.target);
    const data = Object.fromEntries(formData);
    // Submit data
  };

  return html`
    <form onSubmit=${handleSubmit}>
      <input 
        name="email" 
        type="email" 
        required 
        placeholder="Email"
      />
      <input 
        name="password" 
        type="password" 
        required 
        minlength="8"
        placeholder="Password"
      />
      <button type="submit">Sign Up</button>
    </form>
  `;
}
```

### Controlled Inputs with Signals

```javascript
function SearchBox() {
  const query = useSignal('');
  
  return html`
    <input
      value=${query}
      onInput=${e => query.value = e.target.value}
      placeholder="Search..."
    />
    <div>Results for: ${query}</div>
  `;
}
```

## Progressive Enhancement

### Core Principles

1. **HTML First** - Structure works without JavaScript
2. **CSS for Presentation** - Visual design doesn't require JS
3. **JavaScript for Enhancement** - Adds interactivity and polish

### Example: Accordion

```javascript
// Works without JS (details/summary), enhanced with JS
function Accordion({ items }) {
  const openItems = useSignal(new Set());

  return html`
    <div>
      ${items.map((item, i) => html`
        <details
          key=${item.id}
          open=${openItems.value.has(i)}
          onToggle=${e => {
            const newSet = new Set(openItems.value);
            if (e.target.open) {
              newSet.add(i);
            } else {
              newSet.delete(i);
            }
            openItems.value = newSet;
          }}
        >
          <summary>${item.title}</summary>
          <div>${item.content}</div>
        </details>
      `)}
    </div>
  `;
}
```

## Accessibility Patterns

### Keyboard Navigation

```javascript
function Modal({ isOpen, onClose, children }) {
  const modalRef = useRef(null);

  useEffect(() => {
    if (!isOpen) return;
    
    const handleKeyDown = (e) => {
      if (e.key === 'Escape') onClose();
    };
    
    document.addEventListener('keydown', handleKeyDown);
    modalRef.current?.focus();
    
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [isOpen, onClose]);

  if (!isOpen) return null;

  return html`
    <div
      role="dialog"
      aria-modal="true"
      ref=${modalRef}
      tabindex="-1"
    >
      ${children}
    </div>
  `;
}
```

### ARIA Labels and Live Regions

```javascript
function SearchResults({ results, loading }) {
  return html`
    <div>
      <div
        role="status"
        aria-live="polite"
        aria-atomic="true"
      >
        ${loading ? 'Loading results...' : `${results.length} results found`}
      </div>
      <ul role="list">
        ${results.map(r => html`
          <li key=${r.id}>${r.title}</li>
        `)}
      </ul>
    </div>
  `;
}
```

## Performance Optimization

### Code Splitting

```javascript
import { Suspense, lazy } from 'preact/compat';

const HeavyComponent = lazy(() => import('./HeavyComponent.js'));

function App() {
  return html`
    <${Suspense} fallback=${html`<div>Loading...</div>`}>
      <${HeavyComponent} />
    </${Suspense}>
  `;
}
```

### Memoization

```javascript
import { useMemo } from 'preact/hooks';
import { memo } from 'preact/compat';

// Memoize expensive computations
function DataGrid({ rows }) {
  const sortedRows = useMemo(
    () => rows.sort((a, b) => a.name.localeCompare(b.name)),
    [rows]
  );
  
  return html`<table>...</table>`;
}

// Memoize components
const ExpensiveRow = memo(({ data }) => html`
  <tr>
    <td>${data.name}</td>
    <td>${data.value}</td>
  </tr>
`);
```

### Virtual Scrolling

For large lists (1000+ items), consider:
- react-window (via preact/compat)
- Manual implementation with Intersection Observer

## Testing Strategies

### Unit Testing Components

```javascript
import { render } from '@testing-library/preact';
import { html } from 'htm/preact';

test('Counter increments', async () => {
  const { getByText } = render(html`<${Counter} />`);
  const button = getByText(/count:/i);
  
  fireEvent.click(button);
  expect(button.textContent).toBe('Count: 1');
});
```

### E2E Testing

Use Playwright or Cypress for:
- Critical user flows
- Cross-browser testing
- Visual regression testing

## Common Pitfalls

### 1. Overusing Signals for Local State

```javascript
// BAD - Signal not needed for local state
function Toggle() {
  const isOpen = signal(false); // Global signal!
  // ...
}

// GOOD - Use useSignal for component-local state
function Toggle() {
  const isOpen = useSignal(false);
  // ...
}
```

### 2. Forgetting Keys in Lists

```javascript
// BAD - No keys
items.map(item => html`<li>${item.name}</li>`)

// GOOD - Stable keys
items.map(item => html`<li key=${item.id}>${item.name}</li>`)
```

### 3. Missing Error Boundaries

Always wrap async operations in error boundaries:

```javascript
function App() {
  return html`
    <${ErrorBoundary}>
      <${Suspense} fallback=${html`<Loading />`}>
        <${AsyncComponent} />
      </${Suspense}>
    </${ErrorBoundary}>
  `;
}
```

### 4. Inline Function Creation in Loops

```javascript
// BAD - Creates new function every render
items.map(item => html`
  <button onClick=${() => handleClick(item.id)}>
    ${item.name}
  </button>
`)

// GOOD - Create handler outside loop or use data attributes
const handleItemClick = (e) => {
  const id = e.target.dataset.id;
  handleClick(id);
};

items.map(item => html`
  <button onClick=${handleItemClick} data-id=${item.id}>
    ${item.name}
  </button>
`)
```

## CSS Architecture

### Utility-First with Tailwind

Prefer Tailwind utilities for rapid development:

```javascript
html`
  <div class="flex items-center gap-4 p-4 bg-white rounded-lg shadow">
    <img class="w-12 h-12 rounded-full" src=${avatar} />
    <div>
      <h3 class="text-lg font-semibold">${name}</h3>
      <p class="text-gray-600">${email}</p>
    </div>
  </div>
`
```

### Custom CSS When Needed

For complex layouts or animations:

```html
<style>
  @keyframes slideIn {
    from { transform: translateX(-100%); }
    to { transform: translateX(0); }
  }
  
  .sidebar {
    animation: slideIn 0.3s ease-out;
  }
</style>
```

### CSS Modules (with Build Tools)

For component-scoped styles in larger apps:

```javascript
import styles from './Button.module.css';

function Button({ children }) {
  return html`
    <button class=${styles.button}>
      ${children}
    </button>
  `;
}
```

## Security Best Practices

### XSS Prevention

Never use `dangerouslySetInnerHTML` with user content:

```javascript
// BAD - XSS vulnerability
<div dangerouslySetInnerHTML=${{ __html: userInput }} />

// GOOD - Preact escapes by default
<div>${userInput}</div>
```

### CSRF Protection

For forms that mutate state:

```javascript
function DeleteForm({ itemId, csrfToken }) {
  const handleDelete = async () => {
    await fetch(`/api/items/${itemId}`, {
      method: 'DELETE',
      headers: {
        'X-CSRF-Token': csrfToken
      }
    });
  };
  
  return html`
    <button onClick=${handleDelete}>Delete</button>
  `;
}
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.