devx
Technical UI documentation for the DevX visual system. Invoke when extending, refactoring, or redesigning the DevX resources pages, i18n, or related components.
DevX UI System
This skill documents the design and implementation logic of the DevX UI layer used across resources/vscode, resources/terminal, and resources/xfetch pages and their related components.
Companion references:
references/tokens.md: canonical token model for DevX UI, including theme, spacing, sizing, and motion guidancereferences/platform-mapping.md: preferred future file placement for routes, components, data, types, hooks, and helpersreferences/tokens-and-layout.md: compact quick referencereferences/code-structure.md: current recommended structure and responsibilities
Use this skill when:
- building new sections for the DevX resources pages
- extending the VS Code showcase UI
- refactoring layout, CSS modules, or component boundaries
- adding new cards, preview areas, galleries, sliders, or CTA sections
- making UI changes that should remain visually consistent with the existing DevX direction
The goal is not to generate generic UI. The goal is to preserve a very specific product language:
- technical but elegant
- minimal, not decorative
- content-led, not card-led
- dark-mode aware through project theme variables
- responsive without horizontal overflow
- easy for AI agents to extend safely
1. Core Design Intent
The DevX page language is a hybrid of:
- editorial layout
- tool-like UI
- low-noise interface chrome
- strong visual hierarchy through spacing and contrast
It should feel closer to a carefully composed product documentation page than to a marketing landing page full of visual effects.
1.1 Visual Traits
- Prefer flat surfaces over elevated cards.
- Prefer lines, spacing, and alignment over heavy framing.
- Use color as accent and state, not as decoration.
- Keep large sections open and breathable.
- Let screenshots, previews, and code surfaces carry the visual richness.
1.2 What To Avoid
- random gradients in UI chrome
- rounded cards everywhere
- shadow-heavy surfaces
- excessive Tailwind utility styling inside page-specific UI
- decorative wrappers with no structural purpose
- deeply nested component trees for simple presentation logic
2. Theme Variable Contract
Always prefer project-level CSS variables instead of hardcoded UI colors for page chrome.
For the broader token model and future semantic token layering, see references/tokens.md.
Primary variables used by the current DevX page:
--background--foreground--primary--text-muted--border--card-bg
2.1 Usage Rules
--background: the main page surface--foreground: primary readable text--text-muted: secondary copy, technical descriptions, metadata--primary: active states, underline states, primary buttons, branded emphasis--border: separators, subtle outlines, technical dividers--card-bg: optional blending helper for mixed surfaces
2.2 Color Strategy
- Main layout chrome should derive from theme variables.
- Interactive editor previews may use derived or theme-specific preview colors when needed.
- If a showcase simulates a product UI, local CSS variables are acceptable inside that component only.
- Do not let local preview colors leak into global page chrome.
3. Typography And Hierarchy
The page uses the project font system already defined in the app. Do not replace the font stack unless explicitly requested.
3.1 Typography Principles
h1should match the scale and weight strategy of other resource pages.- Section titles should be strong but not oversized.
- Eyebrows should be compact, technical, and sparingly used.
- Description text should stay readable, usually within
56chto68ch.
3.2 Case Rules
- Avoid forcing uppercase across the interface unless there is a very specific technical label or micro-label.
- Prefer sentence case or title case for human-facing UI.
4. Layout Principles
4.1 Section Composition
Each large section should follow a simple structure:
- identity or context
- main content surface
- supporting utility or CTA
Examples:
xscriptor themes: selector, preview/video, palette, actionsxglass: icon, copy, slider, CTA
4.2 Alignment
- Use left alignment by default.
- Avoid arbitrary centering in dense UI sections.
- Align controls and copy to consistent inner edges.
- Let media blocks fill width, but keep textual blocks within readable width.
4.3 Spacing
- Use spacing to create hierarchy before adding borders.
- Prefer section gaps of
1remto2reminside components. - Prefer larger inter-section gaps across page modules.
- If a divider feels necessary, first verify whether spacing contrast is sufficient.
5. Responsive Rules
This page must work without horizontal scrolling on mobile.
5.1 Non-Negotiables
- Always set
min-width: 0on grid and flex children that can shrink. - Never leave desktop-only
min-widthvalues active on mobile. - Allow text to wrap using
overflow-wrap: anywherewhere code-like or long labels appear. - Convert horizontal selectors into stacked or grid layouts on smaller screens.
- Convert action groups to full-width buttons on mobile when needed.
5.2 Media Blocks
- Sliders and screenshots may be visually large, but must still respect viewport width.
- Increase height through
min-height, not through unsafe width assumptions. - On mobile, reduce density before reducing readability.
5.3 Preview Surfaces
- Editor-like previews may have internal scroll.
- Internal scroll must not cause global horizontal page overflow.
- Internal scroll areas should retain keyboard focusability when accessibility matters.
6. Motion Rules
Motion on this page should be calm, structural, and secondary.
6.1 Use Motion For
- section reveal on scroll
- subtle state change between preview modes
- opacity/translate entrance
- indicator transitions
6.2 Do Not Use Motion For
- bounce
- spring-heavy interactions
- decorative looping transforms unrelated to content
- large parallax effects
6.3 Motion Style
- prefer
easeorease-out - keep durations short to medium
- respect
prefers-reduced-motion - use CSS transitions when possible for simple reveal and dim states
7. Component Boundaries
The DevX page already follows a useful separation pattern. Keep that logic.
For the future-oriented file placement model, see references/platform-mapping.md.
7.1 Reusable Components Belong In
src/app/components/xcomponents/
Examples:
vscode-theme-galleryxglass-showcasevscode-resource-sectionsrepo-cardicons
7.2 Route-Specific Files Belong Near The Route
src/app/resources/vscode/
Examples:
page.tsxvscode.module.css- route-only references or static notes
7.3 Data And Types
Use:
src/data/...for structured content/configurationsrc/types/...for shared types
Do not mix route data arrays directly into large page files when the structure is reusable or likely to grow.
8. Ideal Project Structure
For this project, the recommended structure is:
src/
app/
resources/
vscode/
page.tsx
vscode.module.css
references.md
components/
xcomponents/
vscode-resource-sections/
vscode-theme-gallery/
xglass-showcase/
repo-card/
icons/
data/
resources/
vscode/
vscodeThemes.data.ts
types/
resources/
vscode.types.ts
8.1 Structure Rules
- page files should compose, not contain large UI logic
- route CSS modules should style layout, not complex embedded widgets
- reusable widgets should own their own
module.css - data should be serializable and easy to inspect
- component APIs should remain explicit and prop-driven
9. Styling Rules
9.1 Preferred Styling Method
- use
module.cssfor page and component styling - prefer CSS Modules as the default styling approach for feature UI
- use project theme variables
- use local CSS custom properties for component-specific preview theming
9.2 Tailwind Usage
- avoid depending on Tailwind for the main page composition when the section already has a dedicated CSS module
- use Tailwind only for trivial layout helpers when a dedicated CSS module would be unnecessary
- do not mix complex Tailwind class soup with carefully structured CSS modules
9.3 Border Radius
- default to
0or very restrained rounding for technical UI - reserve soft rounding only for image assets, media previews, or when explicitly part of the product visual
9.4 Borders And Surfaces
- use borders sparingly
- prefer one structural line over boxed components everywhere
- surfaces should feel integrated, not stacked as disconnected cards
10. Accessibility Rules
The DevX page should be easy to navigate and readable for assistive technologies.
10.1 Required Practices
- provide semantic headings
- use proper
aria-labeloraria-describedbyfor custom interactive areas - keep keyboard navigation viable in tablists, sliders, and scrollable preview regions
- ensure motion has a reduced-motion fallback
- preserve sufficient contrast in primary surfaces and key UI states
10.2 Preview-Specific Practices
- a simulated editor preview should describe itself semantically
- if a palette hides visible labels on mobile, provide equivalent text through
aria-labelortitle - do not set
aria-hiddenon still-interactive visible content
11. Implementation Checklist For AI Agents
Before editing the DevX page, verify:
- Does the new section reuse existing theme variables?
- Is the component route-specific or reusable?
- Will the layout remain overflow-safe on mobile?
- Are spacing and alignment doing the hierarchy work?
- Is motion subtle and optional?
- Is the component accessible with keyboard and screen readers?
- Is data separated from rendering if the content is structured?
- Is the resulting code easier to extend than before?
If the answer to any of these is no, revise the solution before finalizing.
12. Specific Guidance For resources/vscode
The current page is split into two major content stories:
- Xscriptor Themes
- Xglass
12.1 Xscriptor Themes
This section is interactive and data-driven.
It should preserve:
- a selector that feels technical, not decorative
- a hero state that can show video or interactive preview
- preview-local colors that simulate each theme faithfully
- compact supporting metadata and actions
12.2 Xglass
This section is more showcase-oriented.
It should preserve:
- clear product identity through icon + copy
- visually dominant screenshots
- a restrained CTA
- a softer transition from the previous section through reveal and dim logic
13. Output Expectations
When an AI agent extends this page, the expected result is:
- structurally clean
- visually minimal
- thematically consistent
- responsive without hacks
- accessible by default
- easy to maintain by humans after the fact
If a proposed solution is clever but harder to maintain, reject it.
Choose clarity over novelty.
14. i18n — Internationalization Architecture
The project supports three locales: English (en), Spanish (es), and German (de).
14.1 How it works
- All routes live inside
src/app/[locale]/(Next.js dynamic segment). localePrefix: 'always'— every URL includes the locale:/en/,/es/,/de/.- The root
/serves English content directly (static HTML), so users hitting the bare domain get English without a redirect.
14.2 Provider stack
src/app/i18n-provider.tsx ← custom React context (NOT next-intl)
I18nProviderreads locale + messages frommessages/{locale}.json.useT(namespace?)hook returns(key, params?) => stringfor client components..raw<T>(key)returns structured data (e.g. arrays of skill definitions).paramssupports{var}interpolation.
useLocale()hook returns the current locale string ("en" | "es" | "de").
14.3 Architecture rules
| Scope | Mechanism | Files |
|-------|-----------|-------|
| Layout | [locale]/layout.tsx loads JSON messages and passes to I18nProvider | messages/{locale}.json |
| Server component pages | Import JSON directly + prefix URLs with params.locale | resources/page.tsx, repos/page.tsx, terminal/page.tsx |
| Client component pages | Use useT("Namespace") hook | All [locale]/*/page.tsx, shared components |
| Shared components | Use useT("Namespace") hook | Navbar, Footer, ContactForm, SkillNetwork, etc. |
14.4 Navbar locale-aware linking
- All navbar links are prefixed with
/${locale}/at render time. NavLink.jsxstrips the locale prefix fromusePathname()for active detection.- The language selector sits on the far right with a globe SVG icon.
- Desktop: hover to expand a dropdown with ES/DE options.
- Mobile/touch: click to toggle; click outside to close.
- Current locale is highlighted; switching stays on the same page path.
14.5 Internal link rule
Any hardcoded internal link (/resources/vscode, /resources/terminal, /contact, etc.)
must be prefixed with the current locale at render time:
// Server component — use params.locale
const href = `/${locale}/resources/vscode`;
// Client component — use useLocale() hook
const locale = useLocale();
// ...
<Link href={`/${locale}/resources`}>Back</Link>
14.6 Translation files
messages/
en.json ← English (default, also served at /)
es.json ← Spanish
de.json ← German
Flat JSON structure, namespaced by component/page:
{
"Navbar": { "home": "Go home" },
"HomePage": { "heroTitle1": "Discover the" },
"ContactForm": { "nameLabel": "Name*://" }
}
Add new keys under the relevant namespace. Use {variable} syntax for dynamic values.
14.7 _headers + security (build output)
public/
_headers ← CSP, HSTS, X-Frame-Options (Netlify/Cloudflare format)
robots.txt ← allows crawlers, points to sitemap
sitemap.xml ← all routes × 3 locales with hreflang annotations
.well-known/security.txt
These are copied verbatim to out/ at build time by Next.js static export.
15. Specific Guidance For resources/terminal
The terminal resources page is a data-rich, filterable showcase of terminal themes and emulator installers. It lives at src/app/[locale]/resources/terminal/ with its main component in src/app/components/xcomponents/terminal-resource-sections/.
15.1 Page Structure
section.page ← grid, gap: 1.5rem (mobile: 1.25rem)
header.header ← grid, gap: 0.25rem
h1 ← title + <em> emphasis
p.description ← max-width: 68ch, color: var(--text-muted),
line-height: 1.8 (mobile: 1.7), font-size: 1rem
div.shell ← wrapper from TerminalResourceSections
The TerminalResourceSections shell uses display: grid; gap: clamp(2.5rem, 6vw, 4.5rem) for inter-section spacing.
15.2 Surface / Container Pattern
Every bordered container in the terminal page follows the exact same recipe:
/* Standard surface — used for .controls, .commandCard, .themeCard, .installHint */
border: 1px solid color-mix(in srgb, var(--border) 66%, transparent);
background: color-mix(in srgb, var(--background) 94%, var(--card-bg) 6%);
Padding varies by role:
- Controls panel (
.controls):padding: 1.25rem(mobile:1rem) - Command card (
.commandCard):padding: 1.1rem(mobile:1rem) - Theme card (
.themeCard):padding: 1rem - Install hint (
.installHint):padding: 1.15rem— usesborder: dashedinstead of solid
All these use display: grid; gap: [role-specific]; min-width: 0.
15.3 Section Header Pattern
.sectionHeader { display: grid; gap: 0.25rem; min-width: 0; }
.sectionTitle {
margin: 0; font-size: clamp(1.5rem, 2.2vw, 1.9rem);
line-height: 1.05; color: var(--foreground);
}
.sectionDescription {
margin: 0; color: var(--text-muted);
line-height: 1.7; max-width: 68ch;
}
15.4 Controls / Filters Section
.controls ← surface (see 15.2), gap: 1rem
.controlsHeader ← flex, justify-content: space-between, gap: 1rem
.controlsTitle ← inline-flex, gap: 0.55rem, font-size: 1.1rem
.controlsMeta ← color: var(--text-muted), font-size: 0.88rem
.controlsGrid ← grid, gap: 0.85rem, 1-col → 2-col at 820px+
.control ← grid, gap: 0.35rem
.controlLabel ← color: var(--text-muted), font-size: 0.85rem
.input / .select ← see 15.5
.terminalChips ← flex, gap: 0.5rem, overflow-x: auto
.chip ← see 15.6
15.5 Input / Select Fields
.input, .select {
width: 100%; min-width: 0; padding: 0.75rem 0.85rem;
border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
background: color-mix(in srgb, var(--background) 88%, var(--card-bg) 12%);
color: var(--foreground); outline: none;
transition: border-color 0.2s ease, background-color 0.2s ease;
}
.input::placeholder {
color: color-mix(in srgb, var(--text-muted) 78%, transparent);
}
.input:focus, .select:focus {
border-color: color-mix(in srgb, var(--primary) 62%, var(--border) 38%);
background: color-mix(in srgb, var(--background) 84%, var(--card-bg) 16%);
}
15.6 Chips (Terminal Filter Buttons)
.chip {
flex: 0 0 auto; border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
background: transparent; color: var(--text-muted);
padding: 0.5rem 0.75rem; font-size: 0.84rem; line-height: 1;
white-space: nowrap; cursor: pointer;
}
.chip:hover, .chip:focus-visible {
color: var(--foreground);
border-color: color-mix(in srgb, var(--primary) 40%, var(--border) 60%);
}
.chip[data-active="true"] {
background: color-mix(in srgb, var(--primary) 14%, transparent);
color: var(--primary);
border-color: color-mix(in srgb, var(--primary) 50%, var(--border) 50%);
}
15.7 Terminal Preview Section
The preview container: display: grid; gap: 1rem.
Preview controls row: display: grid; gap: 0.35rem; max-width: 26rem.
15.7.1 Preview Surface
.previewSurface {
position: relative; padding: clamp(1rem, 3vw, 1.6rem);
border: 1px solid color-mix(in srgb, var(--border) 66%, transparent);
background-image: url("/images/resources/terminal/terminal-background.png");
background-size: cover; background-position: center; overflow: hidden;
border-radius: 30px;
}
.previewSurface::after {
content: ""; position: absolute; inset: 0;
background: rgba(0, 0, 0, 0.1);
mix-blend-mode: multiply; pointer-events: none; z-index: 0;
}
15.7.2 Terminal Frame
Inside .previewSurface at z-index: 1; isolation: isolate;:
.terminalFrame {
display: grid; position: relative; max-width: 66rem; margin: 0 auto;
border: 1px solid color-mix(in srgb, var(--border) 66%, transparent);
border-radius: 1.15rem;
background: color-mix(in srgb, var(--background) 92%, var(--card-bg) 8%);
box-shadow:
0 0 0 1px color-mix(in srgb, var(--primary) 12%, transparent),
0 28px 64px rgba(0, 0, 0, 0.38);
overflow: hidden; min-width: 0;
}
The frame uses local CSS custom properties prefixed --t-* set dynamically from JS:
| Variable | Default | Purpose |
|----------|---------|---------|
| --t-bg | #0b0b0b | Terminal background |
| --t-fg | #ededed | Terminal foreground |
| --t-muted | rgba(255,255,255,0.65) | Muted text |
| --t-soft | rgba(255,255,255,0.5) | Soft text |
| --t-dim | rgba(255,255,255,0.4) | Dim text |
| --t-c2 | #34d399 | Syntax: green |
| --t-c3 | #fbbf24 | Syntax: yellow |
| --t-c4 | #60a5fa | Syntax: blue |
| --t-c5 | #a78bfa | Syntax: purple |
| --t-c6 | #5ad4e6 | Syntax: cyan |
15.7.3 Terminal Header
.terminalHeader {
display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
padding: 0.75rem 0.9rem;
background: color-mix(in srgb, var(--background) 86%, var(--card-bg) 14%);
border-bottom: 1px solid color-mix(in srgb, var(--border) 62%, transparent);
}
.trafficLights { display: inline-flex; gap: 0.45rem; }
.light { width: 0.7rem; height: 0.7rem; border-radius: 999px; }
.light[data-variant="close"] { background: #ff5f56; }
.light[data-variant="min"] { background: #ffbd2e; }
.light[data-variant="max"] { background: #27c93f; }
.terminalTitle {
color: var(--text-muted); font-size: 0.86rem;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.terminalTitleAccent { color: var(--primary); font-weight: 700; }
15.7.4 Terminal Body
.terminalBody {
padding: 0.85rem 0.95rem 0.95rem;
background: var(--t-bg); color: var(--t-fg);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
"Liberation Mono", "Courier New", monospace;
font-size: 0.72rem; line-height: 1.5; overflow: hidden;
}
Typography tokens inside the terminal body:
| Class | Color Variable | Weight |
|-------|---------------|--------|
| .noticeTag | var(--t-c6) | 700 |
| .promptUser | var(--t-c2) | 700 |
| .promptHost | var(--t-c5) | 700 |
| .promptSigil | var(--t-c3) | normal |
| .promptCommand | var(--t-c4) | 700 |
| .fetchHeading | var(--t-c2) | 700 |
| .fetchRow dt | var(--t-soft) | normal |
| .fetchRow dd | var(--t-fg) | normal |
| .tokenDim | var(--t-muted) | normal |
| .tokenKey | var(--t-c3) | normal |
| .tokenString | var(--t-c2) | normal |
| .tokenPunct | var(--t-soft) | normal |
| .tokenNumber | var(--t-c5) | normal |
| .inlinePath | var(--t-c4) | normal |
15.7.5 Fetch Grid Layout
At 820px+: grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr). Below 820px: single column.
Fetch swatch: width/height: 0.55rem; border-radius: 999px; border: 1px solid rgba(0,0,0,0.35).
15.8 Command Cards
.commandCard {
display: grid; gap: 0.75rem;
border: 1px solid color-mix(in srgb, var(--border) 66%, transparent);
background: color-mix(in srgb, var(--background) 94%, var(--card-bg) 6%);
padding: 1.1rem; min-width: 0;
}
.commandHeader { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.commandTitle { margin: 0; font-weight: 700; letter-spacing: 0.01em; }
Copy button:
.copyButton {
border: 1px solid color-mix(in srgb, var(--primary) 64%, transparent);
background: transparent; color: var(--primary);
padding: 0.55rem 0.85rem; font-size: 0.78rem; font-weight: 700;
cursor: pointer; flex: 0 0 auto;
}
.copyButton:hover {
background: color-mix(in srgb, var(--primary) 12%, transparent);
border-color: color-mix(in srgb, var(--primary) 78%, transparent);
}
15.9 Code Blocks
.codeBlock, .themeJson {
margin: 0;
border: 1px solid color-mix(in srgb, var(--border) 58%, transparent);
background: color-mix(in srgb, var(--background) 86%, #050505 14%);
padding: 0.9rem 1rem; overflow-x: auto; min-width: 0;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
"Liberation Mono", "Courier New", monospace;
font-size: 0.85rem; line-height: 1.55;
}
The .themeJson variant caps height at max-height: 9.5rem with overflow: auto.
Scrollbar styling for code blocks:
.codeBlock::-webkit-scrollbar { width: 10px; height: 10px; }
.codeBlock::-webkit-scrollbar-track {
background: color-mix(in srgb, var(--background) 86%, #050505 14%);
}
.codeBlock::-webkit-scrollbar-thumb {
background: color-mix(in srgb, var(--primary) 78%, transparent);
border-radius: 999px;
border: 2px solid color-mix(in srgb, var(--background) 86%, #050505 14%);
}
15.10 Theme Cards
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(16.5rem, 1fr));
gap: 1.1rem;
}
.themeCard {
display: grid; gap: 0.85rem;
border: 1px solid color-mix(in srgb, var(--border) 66%, transparent);
background: color-mix(in srgb, var(--background) 94%, var(--card-bg) 6%);
padding: 1rem;
}
.themeHeader { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.themeTitle {
margin: 0; font-size: 1.15rem; line-height: 1.1; letter-spacing: 0.01em;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
Color swatches:
.swatches { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 0.25rem; }
.swatch { width: 100%; aspect-ratio: 1 / 1; border: 1px solid rgba(0, 0, 0, 0.2); }
15.11 Install Hint Box
.installHint {
border: 1px dashed color-mix(in srgb, var(--border) 66%, transparent);
padding: 1.15rem;
background: color-mix(in srgb, var(--background) 96%, var(--card-bg) 4%);
}
15.12 Responsive Thresholds
| Breakpoint | Changes |
|------------|---------|
| 820px+ | .controlsGrid → 2 columns, .fetchGrid → 2 columns, .fetchColumns → 2 columns |
| max-width: 767px | .controls padding → 1rem, .commandCard padding → 1rem, .terminalBody padding → 0.8rem, .fetchRow grid → 6.25rem 1fr |
16. Specific Guidance For resources/xfetch
The xfetch page is a single-file client component at src/app/[locale]/resources/xfetch/page.tsx. It uses a stage-based scroll reveal system with no external component dependencies.
16.1 Page Structure
section.page
div.stack ← grid, gap: clamp(4.5rem, 12vh, 14rem) (mobile: 3.5rem)
section[data-stage="0"] ← stageSurface (header + icon)
section[data-stage="1"] ← stageSurface (screenshots slider)
section[data-stage="2"] ← stageSurface (layout examples)
section[data-stage="3"] ← stageSurface (install commands)
section[data-stage="4"] ← stageSurface (configuration)
section[data-stage="5"] ← stageSurface (usage)
section[data-stage="6"] ← stageSurface (uninstall + CTA)
Each stage section uses the scroll-reveal pattern via IntersectionObserver (see page.tsx).
16.2 Stage Reveal Pattern
Every .stageSurface starts invisible and reveals on scroll:
.stageSurface {
display: grid; gap: 2rem; min-width: 0;
opacity: 0; filter: blur(8px);
transform: translateY(2rem); /* mobile: 1.5rem */
transition: opacity 0.55s ease, filter 0.55s ease, transform 0.55s ease;
}
.stageSurface[data-visible="true"] {
opacity: 1; filter: blur(0); transform: translateY(0);
}
.stageSurface[data-dimmed="true"] {
opacity: 0.34; /* mobile: 0.28 */
filter: blur(6px) saturate(0.72) brightness(0.78);
transform: scale(0.985); /* mobile: scale(0.99) */
}
16.3 Header Section (Stage 0)
.header { display: grid; gap: 0.25rem; min-width: 0; }
.description {
margin: 0; max-width: 68ch; color: var(--text-muted);
line-height: 1.8 (mobile: 1.7); font-size: 1rem;
}
.iconWrap { display: flex; justify-content: center; width: 100%; }
.icon { display: block; width: clamp(4.5rem, 16vw, 5.5rem); height: auto; }
16.4 Screenshots Slider (Stage 1)
.media {
position: relative; overflow: hidden; width: 100%; min-width: 0;
min-height: 40rem; /* mobile: 24rem */
border-radius: 1rem;
border: 1px solid color-mix(in srgb, var(--border) 66%, transparent);
background: color-mix(in srgb, var(--background) 94%, var(--card-bg) 6%);
}
.sliderTrack {
display: flex; width: 300%; height: 100%;
animation: xfetchSlide 15s ease-in-out infinite;
}
.slide {
position: relative; flex: 0 0 33.333%; width: 33.333%;
min-width: 0; min-height: 40rem; /* mobile: 24rem */ margin: 0;
}
.slideImage { object-fit: cover; }
Keyframes:
@keyframes xfetchSlide {
0%, 28% { transform: translateX(0); }
36%, 61% { transform: translateX(-33.333%); }
69%, 94% { transform: translateX(-66.666%); }
100% { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
.sliderTrack { animation: none; transform: translateX(0); }
}
16.5 Section Containers (Stages 2-6)
.section { display: grid; gap: 0.75rem; min-width: 0; }
.sectionTitle { margin: 0; font-size: 1.15rem; color: var(--foreground); }
16.6 Layout Examples (Stage 2)
.layoutsGrid { display: grid; gap: 1rem; }
@media (min-width: 768px) { .layoutsGrid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 767px) { .layoutsGrid { grid-template-columns: 1fr; } }
Layout stack (first 3 examples in a column):
@media (min-width: 768px) {
.layoutStack { display: grid; gap: 1rem; align-content: start; }
}
16.7 Install Section (Stage 3)
.installStack { display: grid; gap: 1rem; }
.installBlock { display: grid; gap: 0.5rem; }
.installLabel { margin: 0; font-size: 0.85rem; color: var(--text-muted); font-weight: 600; }
16.8 Configuration Section (Stage 4)
.configDescription { margin: 0; color: var(--text-muted); line-height: 1.6; font-size: 0.95rem; }
.configList { display: grid; gap: 0.4rem; margin: 0; padding: 0; list-style: none; }
.configItem {
padding: 0.5rem 0.75rem;
background: color-mix(in srgb, var(--background) 86%, #050505 14%);
border-radius: 0.4rem;
border: 1px solid color-mix(in srgb, var(--border) 58%, transparent);
font-family: ui-monospace, monospace; font-size: 0.82rem; color: var(--foreground);
}
.modulesGrid { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.moduleTag {
display: inline-block; padding: 0.25rem 0.5rem; border-radius: 0.3rem;
border: 1px solid color-mix(in srgb, var(--border) 58%, transparent);
background: color-mix(in srgb, var(--background) 90%, var(--primary) 10%);
font-family: ui-monospace, monospace; font-size: 0.78rem; color: var(--primary);
}
16.9 CTA Button (Stage 6)
⚠️ Do NOT hardcode colors. The current button uses #ffc400 / #1a1a1a which breaks the theme contract. Use this pattern:
.button {
display: inline-flex; align-items: center; justify-content: center;
min-height: 2.85rem; padding: 0.78rem 1.8rem;
border: 1px solid var(--primary); color: var(--background); background: var(--primary);
font-size: 0.85rem; font-weight: 700; letter-spacing: 0.02em;
text-decoration: none;
transition: opacity 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}
.button:hover, .button:focus-visible { outline: none; opacity: 0.88; }
@media (max-width: 767px) { .button { width: 100%; text-align: center; } }
The .viewSourceWrap centers the button: display: flex; justify-content: center; padding-top: 0.5rem.
16.10 What NOT To Do On xfetch
- Do NOT use hardcoded hex colors for chrome — always use
var(--primary),var(--background), etc. - Do NOT change the gap rhythm of
.stack— usesclamp(4.5rem, 12vh, 14rem)(mobile:3.5rem) - Do NOT add borders or rounded corners to
.stageSurface— they are layout-only wrappers - Do NOT nest bordered containers without using the standard formula:
border: 1px solid color-mix(in srgb, var(--border) 66%, transparent); background: color-mix(in srgb, var(--background) 94%, var(--card-bg) 6%); - Do NOT add arbitrary card styles — all surfaces must match the surface pattern above
References (4)
code-structure
DevX Code Structure
This file describes the preferred code organization for the DevX UI.
⚠️ The project now uses a locale-based route structure (
src/app/[locale]/). SeeSKILL.md §14 i18nfor the full i18n architecture.
Current Recommended Structure
messages/
en.json ← translations (English)
es.json ← translations (Spanish)
de.json ← translations (German)
public/
_headers ← CSP / security headers (Netlify/Cloudflare)
robots.txt
sitemap.xml ← full locale-aware sitemap
.well-known/
security.txt
src/
app/
layout.tsx ← root layout (html/body + globals only)
page.tsx ← English default at / (wraps [locale]/page with en)
globals.css
i18n-provider.tsx ← I18nProvider + useT() + useLocale() hooks
[locale]/ ← locale dynamic segment
layout.tsx ← I18nProvider, Navbar, Footer, ThemeScript
page.tsx ← home page (client, useT)
contact/
page.tsx
contact.module.css
portfolio/
page.tsx
resources/
page.tsx
resources.module.css
vscode/
page.tsx
vscode.module.css
references.md
terminal/
page.tsx
terminal.module.css
emulators.md
xfetchlogologo.md
examples/
xfetch/
page.tsx
xfetch.module.css
x/
page.tsx
components/ ← shared client components (NOT locale-scoped)
navbar/
navbar.jsx ← locale-aware links + language selector
navLink.jsx ← locale-aware active detection
footer/footer.tsx
contactform/ContactForm.tsx
HeroImageSlider.tsx
SkillNetwork.tsx
DecryptedText.tsx
previewshome/
previewsresources/
xcomponents/
vscode-resource-sections/
vscode-theme-gallery/
xglass-showcase/
terminal-resource-sections/
repo-card/ ← ⚠️ RepoCard still used by resources page
icons/
data/
resources/
resources.data.ts
terminal/
terminalResources.data.ts ← reads colors.md + emulators.md (fs)
vscode/
vscodeThemes.data.ts
types/
resources/
resources.types.ts
terminal.types.ts
vscode.types.ts
Responsibilities
page.tsx (inside [locale]/*/)
- compose the route
- use either direct JSON import (server) or
useT()(client) for text - must prefix internal links with the current locale
[locale]/layout.tsx
- loads
messages/{locale}.json - wraps children in
I18nProvider - renders Navbar, Footer, ThemeScript
- exports
generateStaticParams()returning["en", "es", "de"]
i18n-provider.tsx
- exports
I18nProvider,useT(namespace?),useLocale() useTreturns a function(key, params?) => string.raw<T>(key)returns structured data (arrays, objects)
messages/*.json
- flat JSON, namespaced by component/page
- use
{variable}for interpolation - all three files must stay in sync (same keys, different values)
xcomponents/*
- own reusable or semi-reusable UI blocks
- keep related CSS local to the component folder
- expose an
index.tswhen the folder is intended to be imported from elsewhere
data/*
- store structured content, arrays, configuration, preview presets, and theme definitions
- keep data serializable when possible
types/*
- store shared contracts used across route, data, and components
- avoid duplicating local prop types as global types unless reuse justifies it
Ideal Rules For Future Changes
- if logic is route-only, keep it near the route
- if UI is reusable, move it to
xcomponents - if content is structured, move it to
data - if a type is shared across files, move it to
types - if a component needs its own visual language, give it its own
module.css - all internal links must be prefixed with the current locale
- always add new translation keys to all three
messages/*.jsonfiles - server components that render directly from fs (like
terminalResources.data.ts) stay server; those pages use JSON imports for i18n, notuseT()
Anti-Patterns
- large data arrays inside
page.tsx - multiple unrelated widgets sharing one CSS module
- hardcoded page chrome colors instead of theme variables
- mixing layout, data, and business logic in the same file
- adding Tailwind utility noise to components that already have dedicated CSS modules
- hardcoded internal paths without locale prefix (will 404)
- forgetting to add a key to
messages/de.jsonormessages/es.json - using
next-intlserver APIs (getTranslations,getMessages) — they callheaders()which fails in static export
Preferred Editing Strategy For AI Agents
- inspect route entry and identify locale (
[locale]segment) - read the relevant messages file for existing keys
- identify reusable boundaries
- inspect nearby data and types
- add or update a dedicated component folder if needed
- keep CSS local and readable
- verify responsive behavior after edits
- verify the translation key exists in all three locale files
- verify internal links include the locale prefix
platform-mapping
DevX Platform Mapping
This document explains where DevX-related files should live.
It is intentionally future-oriented. The current repository already follows part of this structure, but AI agents should use this mapping as the preferred target when adding or refactoring DevX UI.
1. Mapping Principle
Group files by responsibility, not by convenience.
The main separation is:
- route composition
- route-local UI
- reusable UI
- structured data
- shared types
- hooks and helpers
- static assets
Do not let page.tsx become the place where everything accumulates.
2. Preferred Future Structure
src/
app/
resources/
page.tsx
vscode/
page.tsx
vscode.module.css
_components/
VscodePageHeader.tsx
VscodeHero.tsx
_lib/
getInitialTheme.ts
references.md
components/
xcomponents/
repo-card/
RepoCard.tsx
RepoCard.module.css
index.ts
icons/
VscodeIcon.tsx
icons.types.ts
index.ts
vscode-theme-gallery/
VscodeThemeGallery.tsx
VscodeThemeGallery.module.css
ThemeSelector.tsx
ThemePalette.tsx
VscodeEditorPreview.tsx
VscodeIntroMedia.tsx
index.ts
xglass-showcase/
XglassShowcase.tsx
XglassShowcase.module.css
index.ts
vscode-resource-sections/
VscodeResourceSections.tsx
VscodeResourceSections.module.css
index.ts
data/
resources/
resources.data.ts
vscode/
vscodeThemes.data.ts
xglass.data.ts
types/
resources/
resources.types.ts
vscode.types.ts
lib/
resources/
vscode/
preview.utils.ts
theme.utils.ts
hooks/
resources/
useThemeSelector.ts
useSectionReveal.ts
This structure does not mean every folder must exist today. It means future additions should move toward this separation instead of increasing file mixing.
3. What Belongs In Each Area
3.1 app/.../page.tsx
Use route files to:
- compose the page
- import prepared data
- assemble major sections
- connect route-level metadata and layout
Do not use route files to:
- hold long data arrays
- define large reusable components
- keep theme preset maps
- accumulate helper functions unrelated to route composition
3.2 app/.../<route>.module.css
Use route CSS modules for:
- page spacing
- route header styling
- outer layout constraints
- route-only wrappers
Do not style deep reusable widgets here if those widgets already have their own folder.
3.3 app/.../_components/
This is the preferred place for route-local components that are not reusable outside one route.
Examples:
- a route-only header block
- a route-only hero wrapper
- a route-only layout shell
Rules:
- if the component is specific to one route, keep it near the route
- if later reused elsewhere, promote it to
xcomponents
3.4 components/xcomponents/
This folder is for reusable or semi-reusable UI blocks.
A component belongs here when at least one of these is true:
- it can be reused by another route
- it expresses a product-level UI pattern
- it has a self-contained API
- it owns meaningful internal styling and behavior
Examples:
RepoCardVscodeThemeGalleryXglassShowcase- shared icon components
3.5 data/
Put serializable structured content here.
This includes:
- card definitions
- theme lists
- palette metadata
- preview preset data
- CTA link definitions
- product showcase slides
Rules:
- prefer plain objects and arrays
- keep data inspectable
- avoid storing JSX in data unless the project has a strong reason
- keep route/domain grouping explicit
Good examples:
src/data/resources/resources.data.tssrc/data/resources/vscode/vscodeThemes.data.ts
3.6 types/
Put shared domain contracts here.
A type belongs in types/ when it is used across:
- route files
- data files
- reusable components
- helper functions
Examples:
ResourceRepoVscodeTheme- preview-related domain contracts
Do not move every local prop type into types/.
Keep local-only prop interfaces next to the component when they are not reused.
3.7 lib/
Use lib/ for pure helpers and transformation logic.
Examples:
- preview token derivation
- theme lookup helpers
- URL normalization
- serialization-safe formatters
Rules:
- keep helpers pure when possible
- avoid mixing React rendering with
lib/ - if the logic depends on hooks or component lifecycle, it does not belong here
3.8 hooks/
Use hooks/ for shared React state behavior.
Examples:
- keyboard-driven selector logic
- section visibility / intersection observer logic
- reduced-motion helpers
Rules:
- only extract a hook when the behavior is meaningful or reused
- do not create hooks just to move a few lines out of a component
4. File Placement Rules By Artifact
Use this decision guide when creating a new file.
4.1 Data
If the artifact is:
- serializable
- content-like
- theme metadata
- configuration for rendering
Place it in data/.
4.2 Types
If the artifact is:
- a shared interface
- a shared type alias
- a contract used by data plus UI
Place it in types/.
4.3 Local Prop Types
If the type is used only by one component or one folder:
- keep it next to the component
- or keep it inline when it stays small and readable
Do not globalize local implementation details.
4.4 Reusable Components
If the artifact is:
- a UI block reused or likely to be reused
- independently styled
- prop-driven
Place it in components/xcomponents/.
4.5 Route-Only Components
If the artifact is:
- tightly coupled to a single route
- not expected to be reused
- mostly compositional
Place it in that route's _components/.
5. Domain Grouping Strategy
Prefer grouping by domain first, then by artifact.
Good:
data/
resources/
vscode/
vscodeThemes.data.ts
Also good:
types/
resources/
vscode.types.ts
Avoid flat growth like:
data/
a.ts
b.ts
c.ts
d.ts
when the project already has clear domains.
6. Current vs Ideal Model
The current codebase already uses:
src/data/...src/types/...src/app/components/xcomponents/...
That is a solid base.
The future improvement is not to undo that structure, but to refine it further:
- keep route-only pieces near the route
- keep reusable pieces in
xcomponents - keep data and types domain-grouped
- keep helpers and hooks out of
page.tsx
7. Anti-Patterns
Avoid these placements:
- large arrays inside
page.tsx - route-specific helper logic inside reusable component folders
- shared domain types hidden inside one component folder
- deeply reusable icons stored inside a route directory
- one CSS module styling multiple unrelated widgets
- data files exporting JSX-heavy structures when plain data would work
8. AI Agent Checklist
Before adding a new file, decide:
- is this composition, UI, data, type, hook, or utility?
- is it route-local or reusable?
- is it serializable or render-specific?
- is the type shared across files or only local?
- will this placement still make sense after the feature grows?
If the answer points to future reuse or shared ownership, avoid placing it in the route file by default.
The goal is a structure that remains readable after expansion, not only one that feels fast in the moment.
tokens
DevX Tokens
This document defines the preferred token model for the DevX UI system.
It is intentionally future-facing. Some of these tokens are already reflected in the current implementation, while others describe the structure that AI agents should preserve or move toward in future refactors.
1. Token Layers
DevX uses three token layers:
- app-level theme tokens
- DevX semantic UI tokens
- component-local preview tokens
Keep these layers separate.
1.1 App-Level Theme Tokens
These come from the project theme and must drive page chrome first:
--background--foreground--primary--text-muted--border--card-bg
Use them for:
- page backgrounds
- route headers
- section framing
- separators
- default buttons
- default text
Do not replace these with hardcoded colors in route UI unless the component is simulating a product preview.
1.2 DevX Semantic UI Tokens
When DevX grows, prefer introducing semantic aliases instead of repeating raw project tokens everywhere.
Examples:
--devx-page-bg--devx-page-fg--devx-accent--devx-muted--devx-line--devx-surface--devx-surface-strong--devx-action-bg--devx-action-fg
Recommended mapping:
:root {
--devx-page-bg: var(--background);
--devx-page-fg: var(--foreground);
--devx-accent: var(--primary);
--devx-muted: var(--text-muted);
--devx-line: var(--border);
--devx-surface: var(--card-bg);
--devx-surface-strong: color-mix(in srgb, var(--card-bg) 72%, var(--background));
--devx-action-bg: var(--primary);
--devx-action-fg: var(--background);
}
These semantic aliases are optional today, but they are the preferred future model if DevX expands beyond one page.
1.3 Component-Local Preview Tokens
Preview components may define local custom properties when they simulate a product UI, such as a VS Code window.
Examples:
--preview-editor-bg--preview-editor-chrome--preview-sidebar-bg--preview-panel-bg--preview-status-bg--preview-status-fg--preview-terminal-bg--preview-terminal-header
Rules:
- local preview tokens belong inside the preview component
- they must not become page-level styling defaults
- they may be derived from theme data files
- they may change per showcased product theme
2. Color Roles
DevX should feel technical, minimal, and low-noise.
2.1 Primary Roles
- background: main page surface
- foreground: main readable text
- muted: supporting descriptions and metadata
- accent: active underline, key CTA, focused state
- line: dividers, section separators, subtle technical framing
- surface: optional distinct blocks when a visual grouping is needed
2.2 Usage Rules
- use accent color to indicate state, not decoration
- prefer one active signal over multiple competing highlights
- rely on spacing before adding extra borders
- keep large surfaces visually flat
- avoid shadow-heavy elevation
3. Typography Tokens
DevX inherits the project font stack. Do not introduce a new font system unless explicitly requested.
Recommended semantic typography tokens:
:root {
--devx-text-page-title: clamp(2.2rem, 4vw, 3.6rem);
--devx-text-section-title: clamp(1.35rem, 2vw, 1.9rem);
--devx-text-body: 1rem;
--devx-text-body-sm: 0.9375rem;
--devx-text-meta: 0.8125rem;
--devx-text-label: 0.75rem;
}
3.1 Typography Rules
- page titles must match the scale strategy of other resource pages
- section titles should be strong but restrained
- labels should be compact and quiet
- long descriptions should usually stay within
56chto68ch - avoid forced uppercase for user-facing interface labels
4. Spacing Scale
Use a restrained spacing rhythm.
Recommended scale:
:root {
--devx-space-2xs: 0.25rem;
--devx-space-xs: 0.5rem;
--devx-space-sm: 0.75rem;
--devx-space-md: 1rem;
--devx-space-lg: 1.5rem;
--devx-space-xl: 2rem;
--devx-space-2xl: 3rem;
--devx-space-3xl: 4.5rem;
}
Suggested usage:
2xstoxs: micro gaps, icon alignment, token chipssmtomd: standard inner padding and control spacinglgtoxl: section-internal grouping2xland above: major page separation
5. Sizing Tokens
DevX should favor layout clarity over decorative scaling.
Recommended future tokens:
:root {
--devx-content-max-width: 84rem;
--devx-copy-max-width: 68ch;
--devx-preview-min-height: 26rem;
--devx-slider-min-height: 28rem;
--devx-control-height: 2.75rem;
--devx-action-height: 2.875rem;
}
Rules:
- keep copy width readable
- let media be large, but still overflow-safe
- increase media height with
min-height, not with unsafe fixed widths - preserve
min-width: 0on shrinkable layout children
6. Borders, Radius, and Surfaces
DevX is not a card-heavy language.
Recommended tokens:
:root {
--devx-radius-none: 0;
--devx-radius-soft: 0.75rem;
--devx-border-width: 1px;
}
Rules:
- default to
--devx-radius-nonefor technical UI - use soft radius only for media, video, or image treatments when requested
- prefer single structural lines over fully boxed stacks
- use surfaces only when grouping materially improves comprehension
7. Motion Tokens
Motion should be subtle and structural.
Recommended tokens:
:root {
--devx-motion-fast: 160ms;
--devx-motion-base: 240ms;
--devx-motion-slow: 420ms;
--devx-ease-standard: ease;
--devx-ease-exit: ease-out;
}
Rules:
- use motion for reveal, dim, active-state transition, and mode switching
- avoid bounce, elastic, or decorative looping motion in page chrome
- respect
prefers-reduced-motion - use CSS transitions first for simple state changes
8. Token Naming Conventions
Use names that communicate role instead of appearance.
Prefer:
--devx-action-bg--devx-line--preview-status-bg
Avoid:
--yellow-1--dark-border-2--button-blue
8.1 Prefix Rules
- use
--devx-*for page/system-level tokens - use
--preview-*for component-local simulated UI tokens - reuse project tokens directly when no semantic alias is needed
9. Token Ownership
This is the preferred future ownership model:
- global theme tokens live in the app theme layer
- DevX semantic aliases live in a DevX-specific shared stylesheet if the system expands
- component-local preview tokens live inside the relevant component module or component root
- theme-specific preview values come from
src/data/..., not from route files
9.1 Future File Placement
If DevX becomes a broader system, the preferred future token placement is:
src/
styles/
tokens/
theme.css
devx.css
If DevX remains route-scoped, keep semantic aliases local and minimal instead of creating an unnecessary global layer.
10. AI Agent Guidance
Before introducing a new token, ask:
- is this already covered by the project theme?
- is this a DevX semantic role reused across sections?
- is this only needed inside one preview component?
Choose the narrowest correct scope.
- if the token is global, keep it global
- if it belongs to DevX UI chrome, use a
--devx-*semantic token - if it only styles one simulated product window, keep it local to that component
The goal is not to create more tokens. The goal is to create a cleaner token hierarchy.
tokens-and-layout
DevX Tokens And Layout
This file provides a compact reference for AI agents working on the DevX UI.
Theme Variables
Use existing project variables first:
--background--foreground--primary--text-muted--border--card-bg
Text Roles
- Page title: primary route label, same visual weight as other resource pages
- Eyebrow: optional, compact, technical, low-volume
- Section title: strong but not oversized
- Description: readable, usually capped to
56chto68ch - Metadata: smaller, quieter, never competing with the title
Spacing Rhythm
- tight grouping:
0.25remto0.5rem - standard inner spacing:
0.75remto1rem - section spacing:
1.25remto2rem - major page separation:
3.5remand above
Alignment Rules
- default to left alignment
- avoid centering dense UI content
- align headings, descriptions, and actions to the same inner edge
- screenshots may fill width, but copy should stay readable
Borders And Radius
- default section radius:
0 - image media may use restrained rounding
- prefer subtle borders and separators over boxed card stacks
Buttons
- primary:
--primarybackground with--backgroundtext - secondary: transparent background with
--primaryborder and text - mobile: stack buttons to full width when space is limited
Motion
- use subtle opacity, blur, and translate transitions
- prefer CSS transitions for reveals and section dimming
- respect
prefers-reduced-motion
Responsive Rules
- set
min-width: 0on shrinkable flex/grid children - prevent horizontal overflow at all times
- convert horizontal lists into grids or stacked layouts on mobile
- allow wrapping for code-like content and long labels
Preview Rules
- simulated editor windows may use local preview variables
- preview-local colors should never replace page-level theme variables
- internal scroll is allowed, but page-wide horizontal scroll is not