Separate things that change for different reasons

In a catalog like Costa Clara, changing filters shouldn't require reviewing the menu. Separating responsibilities makes it easier to find where a change belongs.

Cohesion should be high: a module groups related tasks. Coupling should be low: it needs to know few details about other modules. Creating files alone achieves neither.

A module with a specific task

navigation.js
export function initNavigation() {
  const button = document.querySelector('[data-menu-button]');
  const menu = document.querySelector('[data-menu]');
  if (!button || !menu) return;

  button.addEventListener('click', () => {
    const open = button.getAttribute('aria-expanded') !== 'true';
    button.setAttribute('aria-expanded', String(open));
    menu.hidden = !open;
  });
}

The HTML needs those attributes and a consistent initial state. This example demonstrates code separation; a complete menu also requires keyboard, focus and responsive behavior checks.

An entry point for initialization

app.js
import { initNavigation } from './navigation.js';
import { initFilters } from './filters.js';

initNavigation();
initFilters();
index.html
<script type="module" src="js/app.js"></script>

Functions are exported from their module and imported where needed. Serve the website over HTTP so modules load correctly.

When to stop splitting

A useful boundary is a responsibility you can name: navigation, filters or contact. If each file makes you jump to five others to understand a few lines, review the separation.

In this portfolio, cards exist in HTML. The projects module only changes which ones are shown. An interactive enhancement doesn't need to control the whole structure.