# Soc UI

> Applies separation-of-concerns rules for organizing frontend CSS and JavaScript across a multi-page website or web app - deciding what goes into global files, into component files, or stays page-local, and keeping structure, styling and behavior apart. Use when writing, adding, or refactoring custom styles or client-side scripts in a multi-page frontend (React, Next.js, Vue, Laravel/Blade, plain HTML), when creating new pages or UI components like modals, or when the user asks where CSS or JS should live or how to split stylesheets and scripts.

- Skill: `seym0n/soc-ui` (Agent Skill)
- Install (CLI): `npx skillmds@latest add seym0n/soc-ui`
- Raw SKILL.md: https://api.skillmd.com/api/skills/seym0n/soc-ui/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: Seym0n (https://skillmd.com/u/seym0n)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/seym0n/soc-ui

---


# Separation of Concerns (SoC) for UI Styling and Scripts

## When to Use

Use this skill whenever you write or restructure custom CSS or frontend JavaScript in a project that spans multiple pages, regardless of framework. It applies when adding a new page, adding a reusable component (modal, card, quote block), or cleaning up a stylesheet or script that has grown too large.

## Before You Start

1. Inspect the existing project structure. If the project already has a clear convention for stylesheets or scripts (e.g. CSS Modules, a `components/` folder with co-located files, a `hooks/` or `lib/` folder), follow it instead of introducing a new one.
2. If the project uses a utility framework such as Tailwind, prefer utility classes and only write custom CSS for what utilities cannot express cleanly. The CSS rules below then apply to that custom CSS.

## The Three Tiers

Both CSS (S1) and JavaScript (S2) are sorted into the same three tiers. Never put everything into a single file by default, and never duplicate the same code across several pages.

| Tier | Scope | Where it lives |
|------|-------|----------------|
| 1 | Global | Used on all pages | One global file (`app.css`, `app.js`, root layout) |
| 2 | Shared component | Used on several, but not all, pages | Short: global file under a clear header. Longer or self-contained: own file (`modal.css`, `modal.js`) |
| 3 | Page-specific | Used on exactly one page | Short: on the page itself. Long: own file for that page (`pricing.css`, `pricing.js`) |

As a guideline, "short" means roughly under 30 lines. Readability of the page file matters more than an exact count. When in doubt about Tier 2, prefer a separate component file: it keeps the global file small and makes the component easy to find, move and delete.

### Promotion rule

When page-specific code starts being used on a second page, move it up to Tier 2 instead of copying it. When Tier 2 code ends up on every page, move it to Tier 1.

## S1: CSS Styling

- **Tier 1:** Layout, navigation, footer, typography, color variables and resets go into one global stylesheet, e.g. `app.css`, `globals.css` or `style.css`, depending on the framework.
- **Tier 2:** A short component style may live in the global stylesheet under a comment header (e.g. `/* === Modal === */`). A longer or self-contained component gets its own stylesheet, e.g. `modal.css`, imported only where the component is used, or from the global stylesheet if it appears on most pages.
- **Tier 3:** Short page styles stay on the page (a `<style>` block, a scoped style, or the page's CSS Module). Long page styles move into a dedicated stylesheet, e.g. `pricing.css`, loaded only on that page.

## S2: Frontend JavaScript

- **Tier 1:** Behavior needed on every page (navigation toggle, theme switch, global event setup) goes into the global entry script, e.g. `app.js`. Shared helpers (fetch wrapper, formatting, validation) go into small modules in a `utils/` or `lib/` folder and are imported where needed, not attached to `window`.
- **Tier 2:** Logic for a reusable component lives in its own module, e.g. `modal.js`, exporting an init function (or a hook/composable in component frameworks) and imported only on pages that use it. Only very small shared behavior used on most pages may stay in `app.js`, grouped under a comment header.
- **Tier 3:** Short page logic stays with the page (the page component, or a small module script in the page). Long page logic moves into a dedicated file, e.g. `pages/pricing.js`, loaded only on that page.

### Keep structure, style and behavior apart

- Do not use inline event handlers (`onclick="..."`) in HTML; attach listeners in the script.
- Do not set visual styles directly from JS (`el.style.display = ...`) for static states; toggle CSS classes (e.g. `is-open`) and define the look in CSS.
- Use `data-*` attributes as JS hooks (e.g. `data-modal-open`) instead of styling classes, so renaming a class for design reasons never breaks behavior.
- Separate non-UI logic (API calls, data transformation, business rules) from DOM or rendering code, e.g. in `lib/` or `services/`, so it can be reused and tested independently.

### Pair component files

When a component has both styles and behavior, keep them together, e.g. `components/modal/modal.css` and `components/modal/modal.js`, or `Modal.jsx` next to `Modal.module.css`.

## Example

A website has six pages:

- All six share the same navigation bar → its styles go into `app.css`, its mobile menu toggle into `app.js` (Tier 1).
- Three pages use a modal spanning many lines → it gets `modal.css` and `modal.js`, imported on those three pages (Tier 2). A very small modal could instead live in the global files under a `/* === Modal === */` header.
- One page has a quote block with four lines of CSS and a three-line "copy quote" button handler → both stay on that page (Tier 3, short).
- Another page has a custom animation with 80 lines of CSS and a 120-line pricing calculator → they move to `hero-animation.css` and `pricing.js`, loaded only on that page (Tier 3, long).

## Framework Notes

- **React / Next.js:** Import global styles once at the app root (root layout or `_app`). For components and pages, prefer co-located CSS Modules such as `Modal.module.css` next to `Modal.jsx`. Extract reusable stateful logic into custom hooks (e.g. `useModal`) and non-UI logic into `lib/`. In the Next.js App Router, keep `'use client'` components as small as possible and only where interactivity is needed.
- **Vue:** Global styles and setup in the entry file; component and page styles in `<style scoped>` blocks, or a separate file for long styles. Extract reusable logic into composables (e.g. `useModal`).
- **Laravel (Blade + Vite):** Global styles and scripts in `resources/css/app.css` and `resources/js/app.js`. Component or page files live in `resources/css/` and `resources/js/`, must be added to the `input` array in `vite.config.js`, and are loaded with `@vite(...)` in the view that needs them (e.g. via `@push('styles')` and `@push('scripts')`).
- **Plain HTML:** Link the global stylesheet and script on every page, and additional files only on the pages that use them. Load scripts with `<script type="module" src="...">`, which is deferred by default.

## Avoid

- One monolithic stylesheet or script containing page-specific code for every page.
- Copy-pasting the same rules or functions into multiple page files.
- Inline `style="..."` attributes for static styling and inline `on*` event handlers.
- Global variables on `window` for sharing code between files; use module imports.
- Creating a separate file for every few lines of code, which fragments the project without benefit.
