React Router Development
remix-run/react-router
Guides work on React Router apps by first identifying whether the app uses Framework, Data or Declarative mode, then loading the matching reference and the installed package docs.
Signs of taste in web UI. An agent skill from jamditis/claude-skills-journalism.
$ npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install jamditis/claude-skills-journalism web-ui-best-practices --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/jamditis/claude-skills-journalism.git skills-src && mkdir -p .claude/skills && cp -r skills-src/dev-toolkit/skills/web-ui-best-practices .claude/skills/web-ui-best-practices && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "web-ui-best-practices" agent skill from https://github.com/jamditis/claude-skills-journalism/tree/master/dev-toolkit/skills/web-ui-best-practices into .claude/skills/web-ui-best-practices/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-ui-best-practices", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/jamditis/claude-skills-journalism/tree/master/dev-toolkit/skills/web-ui-best-practicesType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install jamditis/claude-skills-journalism web-ui-best-practices --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jamditis/claude-skills-journalism.git skills-src && mkdir -p .agents/skills && cp -r skills-src/dev-toolkit/skills/web-ui-best-practices .agents/skills/web-ui-best-practices && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "web-ui-best-practices" agent skill from https://github.com/jamditis/claude-skills-journalism/tree/master/dev-toolkit/skills/web-ui-best-practices into .agents/skills/web-ui-best-practices/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-ui-best-practices", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install jamditis/claude-skills-journalism web-ui-best-practices --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jamditis/claude-skills-journalism.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/dev-toolkit/skills/web-ui-best-practices .cursor/skills/web-ui-best-practices && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "web-ui-best-practices" agent skill from https://github.com/jamditis/claude-skills-journalism/tree/master/dev-toolkit/skills/web-ui-best-practices into .cursor/skills/web-ui-best-practices/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-ui-best-practices", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/jamditis/claude-skills-journalism.git --path dev-toolkit/skills/web-ui-best-practices--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install jamditis/claude-skills-journalism web-ui-best-practices --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jamditis/claude-skills-journalism.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/dev-toolkit/skills/web-ui-best-practices .gemini/skills/web-ui-best-practices && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "web-ui-best-practices" agent skill from https://github.com/jamditis/claude-skills-journalism/tree/master/dev-toolkit/skills/web-ui-best-practices into .gemini/skills/web-ui-best-practices/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-ui-best-practices", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install jamditis/claude-skills-journalism web-ui-best-practicesInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/jamditis/claude-skills-journalism.git skills-src && mkdir -p .github/skills && cp -r skills-src/dev-toolkit/skills/web-ui-best-practices .github/skills/web-ui-best-practices && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "web-ui-best-practices" agent skill from https://github.com/jamditis/claude-skills-journalism/tree/master/dev-toolkit/skills/web-ui-best-practices into .github/skills/web-ui-best-practices/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-ui-best-practices", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install jamditis/claude-skills-journalism web-ui-best-practices --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jamditis/claude-skills-journalism.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/dev-toolkit/skills/web-ui-best-practices .opencode/skills/web-ui-best-practices && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "web-ui-best-practices" agent skill from https://github.com/jamditis/claude-skills-journalism/tree/master/dev-toolkit/skills/web-ui-best-practices into .opencode/skills/web-ui-best-practices/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-ui-best-practices", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
web-ui-best-practicesSigns of taste in web UI. An agent skill from jamditis/claude-skills-journalism.
Web UI Best Practices is an agent skill from jamditis/claude-skills-journalism. Signs of taste in web UI. Use when building or reviewing web interfaces, dashboards, SaaS apps, or internal tools.
Its SKILL.md is about 3.5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files (for example `agents/openai.yaml`).
It sits in Frontend & Design, covering Frontend development. The repository describes itself as: Claude Code skills for journalism, media, and academia - verification, FOIA, data journalism, academic writing, and more. The licence is MIT.
Read from SKILL.md and the folder at commit e3e2172. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are css and javascript).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Web UI Best Practices loads about 3.5k tokens when it runs. Until then it costs about 34 tokens; SKILL.md has 1,292 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from jamditis/claude-skills-journalism at commit e3e2172, republished under its MIT licence (© jamditis). 1,292 words, ~3,451 tokens.
.claude/skills/web-ui-best-practices/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.Principles for building web interfaces that feel fast, intentional, and respectful of the user's time. Every rule here is a smell test, violating one is fine if you have a reason, violating several means the UI needs work.
Every interaction completes in under 100ms. If it can't, fake it.
will-change and transform for animations, never top/leftperformance.now(), not gut feel// Optimistic delete, remove from UI immediately, reconcile later
async function handleDelete(id) {
setItems(prev => prev.filter(i => i.id !== id));
try {
await api.delete(`/items/${id}`);
} catch {
setItems(prev => [...prev, originalItem]);
toast("Couldn't delete. Restored.");
}
}Never show a spinner when you know the shape of what's coming. Render a skeleton that matches the layout, then swap in real content.
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 4px;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}Four capabilities matured between 2023 and 2026 that change how you build component-level responsive layouts and SPA-like transitions without JavaScript. Reach for them before adding a framework.
Container queries let a component respond to its container's size, not the viewport's. The same card can render in a 300px sidebar and a 900px main column without media-query coordination at the page level.
.card-list {
container-type: inline-size;
container-name: cards;
}
@container cards (min-width: 480px) {
.card { display: grid; grid-template-columns: 120px 1fr; }
}Stable in all major browsers since 2023. Replaces most "the same component in two places needs to look different" hacks.
:has() parent selector:has() lets a parent style itself based on its descendants, the long-requested "parent selector." Useful for marking a form field as in-error, a card as having an attached image, or a row as containing a focused input, all without JS.
/* Highlight a form group when its input has focus */
.form-group:has(input:focus) {
outline: 2px solid var(--color-primary);
}
/* Add bottom margin to articles that contain a figure */
article:has(figure) {
margin-bottom: 2rem;
}Stable in Chrome, Safari, and Firefox since late 2023. Cuts a real category of JS-driven class toggling.
The View Transitions API animates between two DOM states (route changes, modal open/close, list-item swaps) without a framework. The browser snapshots the old state, swaps in the new state, then crossfades or slides between them.
// Same-document transition (Chrome 111+, Safari TP, Firefox behind a flag)
function navigate(newView) {
if (!document.startViewTransition) {
renderView(newView);
return;
}
document.startViewTransition(() => renderView(newView));
}/* Smooth crossfade by default; override per element */
::view-transition-old(*) { animation-duration: 200ms; }
::view-transition-new(*) { animation-duration: 200ms; }Cross-document view transitions (between full page navigations) shipped to Chrome 126 in 2024 and let MPAs feel like SPAs. Pair with prefers-reduced-motion so users with motion sensitivity get an instant swap, not an animation.
animation-timeline: scroll() and animation-timeline: view() drive CSS animations from scroll position instead of wall-clock time. The classic use case is a progress indicator at the top of an article that fills as you scroll.
@keyframes fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.read-progress {
position: fixed; top: 0; left: 0; right: 0; height: 3px;
background: var(--color-primary);
transform-origin: left;
animation: fill linear;
animation-timeline: scroll(root);
}Stable in Chromium-based browsers (Chrome 115+, Edge); not yet in Safari or Firefox as of 2026-05. Use as progressive enhancement; provide a JS fallback or accept a less-flashy baseline elsewhere.
If you need a tour to explain your UI, the UI is wrong. Instead:
Slugs are short, readable, and human-guessable. No UUIDs, no query param soup.
Good: /projects/weather-app
/settings/billing
/docs/api/auth
Bad: /projects/550e8400-e29b-41d4-a716-446655440000
/app?view=settings&tab=billing&subsection=plan
/dashboard#!/module/documents/list?filter=activeUsers leave and come back. Respect that.
localStorage or the server// Persist form state across sessions
function usePersistentForm(key, defaults) {
const [state, setState] = useState(() => {
const saved = localStorage.getItem(key);
return saved ? JSON.parse(saved) : defaults;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(state));
}, [key, state]);
return [state, setState];
}Not more than 3 colors. One primary, one accent, one for danger/destructive. Everything else is shades of gray.
:root {
--color-primary: #2563eb;
--color-accent: #f59e0b;
--color-danger: #ef4444;
--gray-50: #fafafa;
--gray-100: #f4f4f5;
--gray-200: #e4e4e7;
--gray-400: #a1a1aa;
--gray-600: #52525b;
--gray-900: #18181b;
}Hide them unless the user is actively scrolling. Content feels infinite, not trapped.
/* Hide scrollbar across browsers */
.scroll-container {
overflow-y: auto;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE/Edge */
}
.scroll-container::-webkit-scrollbar {
display: none; /* Chrome/Safari */
}Use scroll shadows to hint at overflow without chrome:
.scroll-shadow {
background:
linear-gradient(white 30%, transparent),
linear-gradient(transparent, white 70%) 0 100%,
radial-gradient(farthest-side at 50% 0, rgba(0,0,0,.15), transparent),
radial-gradient(farthest-side at 50% 100%, rgba(0,0,0,.15), transparent) 0 100%;
background-repeat: no-repeat;
background-size: 100% 40px, 100% 40px, 100% 12px, 100% 12px;
background-attachment: local, local, scroll, scroll;
}All navigation is 3 steps or fewer from anywhere. If the user needs more than 3 clicks to reach a destination, flatten the hierarchy.
Cmd+K / Ctrl+K as the escape hatch for power usersEvery app with more than one page needs a command palette.
// Minimal Cmd+K listener
useEffect(() => {
function handleKeyDown(e) {
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
e.preventDefault();
setCommandPaletteOpen(true);
}
}
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, []);Keep the palette simple:
Copy and paste should work everywhere the user expects it.
async function copyToClipboard(text, label = "Copied") {
await navigator.clipboard.writeText(text);
toast(label, { duration: 1500 });
}Larger hit targets for buttons and inputs. WCAG 2.2 (success criterion 2.5.8) sets the floor at 24×24 CSS pixels; Apple's Human Interface Guidelines and most native iOS/Android conventions recommend 44×44 points as the comfortable target. Use 44px as the working minimum for primary actions; 24px as the absolute legal floor for secondary controls (e.g., dense table-row icons).
button, .btn, [role="button"] {
min-height: 44px;
min-width: 44px;
padding: 10px 20px;
}
input, select, textarea {
min-height: 44px;
padding: 10px 12px;
font-size: 16px; /* Prevents iOS Safari zoom on focus */
}One-click cancel. No guilt trips, no dark patterns, no "Are you sure you want to miss out?"
Very minimal. Tooltips are a confession that the UI doesn't speak for itself.
Active voice. Max 7 words per sentence. Talk like a person, not a legal document.
Good: "Project created"
"Saved 2 minutes ago"
"Delete this file?"
Bad: "Your project has been successfully created!"
"Changes were last saved approximately 2 minutes ago"
"Are you sure you want to permanently delete this file? This action cannot be undone."Optical alignment over geometric alignment. The eye doesn't see pixels, it sees weight.
/* Geometric center ≠ optical center */
.play-button svg {
transform: translateX(2px);
}
/* Visually balanced card padding */
.card {
padding: 20px 24px 22px 24px;
}Optimized for L-to-R reading and the F-pattern scan.
Users fear losing work. Prevent it and prove it.
// Warn on unsaved changes
useEffect(() => {
function handleBeforeUnload(e) {
if (hasUnsavedChanges) {
e.preventDefault();
e.returnValue = "";
}
}
window.addEventListener("beforeunload", handleBeforeUnload);
return () => window.removeEventListener("beforeunload", handleBeforeUnload);
}, [hasUnsavedChanges]);Ship a /brand or /press page with a downloadable SVG logo and brand kit. Don't make people screenshot your logo.
Use this when reviewing any web UI:
© jamditis, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 1 other file in dev-toolkit/skills/web-ui-best-practices of jamditis/claude-skills-journalism.
Open the folder on GitHubat commit e3e2172
Web UI Best Practices next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Web UI Best Practices this skilljamditis/claude-skills-journalism | 417 | — | ~3.5k | Automated safety check: Pass | MIT | |
| React Router Developmentremix-run/react-router | 57k | 1 repos | ~1.5k | Automated safety check: Pass | MIT | |
| React UI State PatternsChrisWiles/claude-code-showcase | 6.1k | 8 repos | ~1.6k | Automated safety check: Pass | None | |
| GSAP in Vue, Nuxt and Sveltegreensock/gsap-skills | 16k | 4 repos | ~2.6k | Automated safety check: Pass | MIT | |
| Svelte Core Best Practicesrilldata/rill | 2.9k | 4 repos | ~1.8k | Automated safety check: Pass | Apache-2.0 | |
| Vuetify Playgroundvuetifyjs/vuetify | 41k | — | ~730 | Automated safety check: Pass | Custom licence |
remix-run/react-router
Guides work on React Router apps by first identifying whether the app uses Framework, Data or Declarative mode, then loading the matching reference and the installed package docs.
ChrisWiles/claude-code-showcase
Sets patterns for React interfaces: when to show loading spinners or skeletons, how to surface errors, how to disable buttons during async work and how to handle empty lists.
greensock/gsap-skills
Shows how to use GSAP in Vue, Nuxt, Svelte and other lifecycle-based frameworks: create after mount, scope selectors to the component, and revert on unmount.
rilldata/rill
Rules for writing idiomatic Svelte 5 code: when to reach for runes like state, derived and effect, and how to handle props, attachments and bindings.
vuetifyjs/vuetify
Maintains the Vuetify repo's local Playground.vue so contributors get a realistic reproduction and a short demo they can paste into a pull request description.
tabler/tabler
Starts the right Tabler dev server, keeps it from clashing with builds and verifies changes in the browser before a page or component is handed back.
jamditis/claude-skills-journalism
A skill your agent uses when creating distinct website directions, a client review picker, asset catalog, previews, and Cloudflare-ready handoffs.
jamditis/claude-skills-journalism
Builds an Open Knowledge Format (OKF) knowledge base from existing docs, notes, or a repo.
jamditis/claude-skills-journalism
Local Gitleaks scans for staged changes, push ranges, and full history in private repos, with redacted reports.
jamditis/claude-skills-journalism
Acquire, clean, analyze, verify, visualize, and explain data for journalism.
jamditis/claude-skills-journalism
Creates print-ready HTML that exports to PDF. An agent skill from jamditis/claude-skills-journalism.
jamditis/claude-skills-journalism
Establishes how to find and use skills, requiring Skill tool invocation before any response.
Categories
Signs of taste in web UI. An agent skill from jamditis/claude-skills-journalism. Web UI Best Practices is an agent skill from jamditis/claude-skills-journalism. Signs of taste in web UI.
Web UI Best Practices fits situations like: reviewing web interfaces; tasks that involve Frontend development.
Run `npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a claude-code`. Or copy the skill folder (dev-toolkit/skills/web-ui-best-practices in jamditis/claude-skills-journalism) into .claude/skills/web-ui-best-practices in your project. Claude Code loads it when a task matches its description.
Run `npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a codex`. Or copy the skill folder (dev-toolkit/skills/web-ui-best-practices in jamditis/claude-skills-journalism) into .agents/skills/web-ui-best-practices in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jamditis/claude-skills-journalism --skill web-ui-best-practices -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/web-ui-best-practices, .gemini/skills/web-ui-best-practices, .github/skills/web-ui-best-practices and .opencode/skills/web-ui-best-practices in your project.
SKILL.md names no scripts, command-line tools or credentials: Web UI Best Practices is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Web UI Best Practices is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.5k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Web UI Best Practices: React Router Development (remix-run/react-router, 57k stars), React UI State Patterns (ChrisWiles/claude-code-showcase, 6.1k stars), GSAP in Vue, Nuxt and Svelte (greensock/gsap-skills, 16k stars) and Svelte Core Best Practices (rilldata/rill, 2.9k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
jamditis (a GitHub user) maintains it in jamditis/claude-skills-journalism, which has 417 GitHub stars. The repository holds 53 skills in this directory. The repository was last updated on October 4, 2026.
Source: jamditis/claude-skills-journalism on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.