- This template still needs a UI component library. Choose one like{" "}
-
- shadcn/ui
- {" "}
- or{" "}
-
- Tailwind Plus
-
- . The theme in globals.css uses shadcn's semantic
- colour naming convention. Your choice affects how to proceed.
-
-
-
shadcn/ui
-
- You're ready to go. The colour variables in{" "}
- globals.css already match shadcn's naming (
- --background, --foreground,{" "}
- --primary, --muted, etc.), so installed
- components inherit your theme automatically. To customise colours,
- change the values in :root and .dark
- —all components update instantly.
-
-
-
Tailwind Plus
-
- Tailwind Plus includes UI Kit (Catalyst) and UI Blocks. The UI Kit
- typically goes into components/ui, whilst blocks go into{" "}
- page.tsx or components/sections/. Both use
- Tailwind's default palette (zinc, gray,{" "}
- indigo, etc.) rather than semantic names.
-
-
- To theme them, either find-replace palette classes with semantic ones
- (bg-zinc-900 → bg-background
- ), or override the palette in @theme
- —for example, --color-zinc-900: oklch(...). Note that
- Blocks are often light-mode only.
-
-
-
- With either library, colours remain centralised. The{" "}
- @theme override method requires no code changes;
- find-replace gives full control over naming but requires editing
- files.
-
-
-
Advanced: Palette Remapping
-
- Instead of directly overriding --color-zinc-900, you can
- define your brand palette first, then remap Tailwind's colours to
- it:
-
-
- {`@theme {
- --color-brand-600: oklch(0.51 0.24 280);
-}
-:root {
- --color-indigo-600: var(--color-brand-600);
- --color-blue-600: var(--color-brand-600); /* both now use your brand */
-}`}
-
-
- Benefits: define colours once with meaningful names, remap multiple
- Tailwind palettes to the same brand colour, clearer separation between
- your palette and Tailwind's naming.
-
-
-
-
- }
- >
- Deploy Now
-
-
-
-
-
- );
-}
+export default Home;
diff --git a/biome.json b/biome.json
index cf56d75..fcde559 100644
--- a/biome.json
+++ b/biome.json
@@ -14,7 +14,8 @@
"!.next",
"!dist",
"!build",
- "!x_docs/reference"
+ "!x_docs/reference",
+ "!app/globals-old.css"
]
},
"css": {
diff --git a/e2e/homepage.spec.ts b/e2e/homepage.spec.ts
index 8315648..21cc7f1 100644
--- a/e2e/homepage.spec.ts
+++ b/e2e/homepage.spec.ts
@@ -2,5 +2,5 @@ import { expect, test } from "@playwright/test";
test("homepage loads successfully", async ({ page }) => {
await page.goto("/");
- await expect(page).toHaveTitle(/Next/);
+ await expect(page).toHaveTitle(/Devflow/);
});
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100755
index 0000000..ad21ce7
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/social-card.jpg b/public/social-card.jpg
deleted file mode 100755
index 35763f0..0000000
Binary files a/public/social-card.jpg and /dev/null differ
diff --git a/x_docs/own/globals-compare.md b/x_docs/own/globals-compare.md
new file mode 100644
index 0000000..352a2ad
--- /dev/null
+++ b/x_docs/own/globals-compare.md
@@ -0,0 +1,983 @@
+# Tailwind Theming Comparison: `globals-old.css` vs My Modern Approach `globals.css`
+
+This document compares the light/dark mode approach from an old file (`globals-old.css`) with the modern Tailwind v4 approach (`globals.css`), and categorises all configuration patterns with explanations.
+
+---
+
+## Light/Dark Mode Comparison
+
+| Aspect | Old File (globals-old.css) | Your File (globals.css) |
+|--------|-------------------------------|-------------------------|
+| **Approach** | Composite utility classes with `dark:` variant | CSS custom properties + `@theme inline` |
+| **Colour Format** | Named scales (light-850, dark-100) | OKLCH (perceptually uniform) |
+| **Theme Switching** | Class-based via Tailwind `dark:` | CSS variables that swap at runtime |
+| **Naming** | Arbitrary (light-850, dark-400) | Semantic (primary, muted, accent) |
+| **Tailwind Version** | v3 patterns | v4 native patterns |
+
+### Verdict: The modern globals.css approach is significantly better
+
+**Why the modern approach wins:**
+
+1. **Runtime theme switching** — CSS variables can be changed via JavaScript without recompiling CSS. This enables features like system preference detection, user preference persistence, and instant theme toggling.
+
+2. **OKLCH colour space** — A modern, perceptually uniform colour space. Unlike HSL or RGB, OKLCH ensures that colours with the same lightness value actually *appear* equally light to human eyes. This produces better gradients and more accessible colour combinations.
+
+3. **Semantic naming** — `bg-primary` communicates intent; `bg-light-850` is meaningless without context. Semantic names make code self-documenting and easier to maintain.
+
+4. **shadcn/ui compatible** — The CSS variable pattern is the standard for shadcn/ui components, Radix UI, and most modern React component libraries. Your setup works out of the box.
+
+5. **DRY (Don't Repeat Yourself)** — Change one variable in `:root` or `.dark`, and all usages update automatically. The old file has 50+ hardcoded light/dark combinations that must be updated individually.
+
+6. **No `!important` spam** — The old file uses `!important` 20+ times, which is a code smell indicating specificity problems. The modern approach avoids this entirely through proper CSS layering.
+
+---
+
+## Old File Categories Explained
+
+The old file contains various utility patterns. Below, each category is explained with context on what it does, why it exists, and what you would need in a modern setup.
+
+---
+
+### 1. Base Settings
+
+```css
+body { font-family: "Inter", sans-serif; }
+:root { --radius: 8px; }
+```
+
+**What it does:**
+Sets the global font family and defines a CSS variable for border radius that can be used throughout the application.
+
+**Why it exists:**
+Centralising design tokens like border radius allows for consistent UI and easy global changes.
+
+**What you'd need:**
+Already handled in your file. Your setup is more sophisticated:
+
+- `--radius` is defined in `:root` and mapped via `@theme inline` to generate `rounded-sm`, `rounded-md`, `rounded-lg`, `rounded-xl` utilities
+- Fonts are defined as CSS variables (`--font-display`, `--font-serif`, `--font-mono`) that integrate with Next.js font optimisation
+
+---
+
+### 2. Background Theme Utilities (17 classes)
+
+```css
+.background-light850_dark100 { @apply bg-light-850 dark:bg-dark-100; }
+.background-light900_dark200 { @apply bg-light-900 dark:bg-dark-200; }
+.background-light900_dark300 { @apply bg-light-900 dark:bg-dark-300; }
+/* ... 14 more variations */
+```
+
+**What it does:**
+Pre-composed utility classes that apply different background colours depending on whether light or dark mode is active. The naming convention `light850_dark100` indicates "use light-850 in light mode, dark-100 in dark mode".
+
+**Why it exists:**
+In Tailwind v3, this was a common pattern to avoid writing `bg-light-850 dark:bg-dark-100` repeatedly in JSX. It keeps component markup cleaner.
+
+**Problems with this approach:**
+
+- Creates dozens of single-purpose classes
+- Arbitrary numbers (850, 100) have no semantic meaning
+- Must create a new class for every light/dark combination needed
+- Tightly couples colour values to class names
+
+**What you'd need:**
+Nothing. Use semantic classes instead:
+
+```html
+
+
+
+
+
+
+```
+
+The modern approach uses semantic names that describe *purpose* (card, muted, secondary) rather than *appearance* (light-900, dark-200).
+
+---
+
+### 3. Text Theme Utilities (16 classes)
+
+```css
+.text-dark100_light900 { @apply text-dark-100 dark:text-light-900 !important; }
+.text-dark200_light800 { @apply text-dark-200 dark:text-light-800 !important; }
+.text-dark300_light700 { @apply text-dark-300 dark:text-light-700; }
+/* ... 13 more variations */
+```
+
+**What it does:**
+Pre-composed text colour classes for light/dark mode. Note that many use `!important` to force specificity.
+
+**Why it exists:**
+Same rationale as background utilities — reduces repetition in markup.
+
+**Problems with this approach:**
+
+- Heavy use of `!important` indicates specificity battles
+- Arbitrary colour values make it hard to understand visual hierarchy
+- No indication of what each colour combination is *for*
+
+**What you'd need:**
+Nothing. Use semantic text colours:
+
+```html
+
+
Secondary text
+
+
+
Secondary text
+```
+
+Common semantic text colours in your setup:
+
+- `text-foreground` — Primary text
+- `text-muted-foreground` — Secondary/subdued text
+- `text-primary` — Brand/accent text
+- `text-destructive` — Error/warning text
+
+---
+
+### 4. Border Utilities
+
+```css
+.light-border { @apply border-light-800 dark:border-dark-300; }
+.light-border-2 { @apply border-light-700 dark:border-dark-400 !important; }
+```
+
+**What it does:**
+Consistent border colours that adapt to light/dark mode.
+
+**Why it exists:**
+Borders often need different opacity/colour in dark mode to remain visible without being too harsh.
+
+**What you'd need:**
+Already handled. Your `@layer base` includes:
+
+```css
+* {
+ @apply border-border outline-ring/50;
+}
+```
+
+This sets a default border colour on all elements using the `--border` CSS variable, which automatically changes between light and dark mode. Simply use the `border` class:
+
+```html
+
+```
+
+---
+
+### 5. Typography Scale (16 classes)
+
+```css
+.h1-bold { @apply text-[30px] font-bold leading-[42px] tracking-tighter; }
+.h2-bold { @apply text-[24px] font-bold leading-[31.2px]; }
+.h2-semibold { @apply text-[24px] font-semibold leading-[31.2px]; }
+.h3-bold { @apply text-[20px] font-bold leading-[26px]; }
+.h3-semibold { @apply text-[20px] font-semibold leading-[24.8px]; }
+.base-medium { @apply text-[18px] font-medium leading-[25.2px]; }
+.base-semibold { @apply text-[18px] font-semibold leading-[25.2px]; }
+.base-bold { @apply text-[18px] font-bold leading-[140%]; }
+.paragraph-regular { @apply text-[16px] font-normal leading-[22.4px]; }
+.paragraph-medium { @apply text-[16px] font-medium leading-[22.4px]; }
+.paragraph-semibold { @apply text-[16px] font-semibold leading-[20.8px]; }
+.body-regular { @apply text-[14px] font-normal leading-[19.6px]; }
+.body-medium { @apply text-[14px] font-medium leading-[18.2px]; }
+.body-semibold { @apply text-[14px] font-semibold leading-[18.2px]; }
+.body-bold { @apply text-[14px] font-bold leading-[18.2px]; }
+.small-regular { @apply text-[12px] font-normal leading-[15.6px]; }
+.small-medium { @apply text-[12px] font-medium leading-[15.6px]; }
+.small-semibold { @apply text-[12px] font-semibold leading-[15.6px]; }
+.subtle-medium { @apply text-[10px] font-medium leading-[13px] !important; }
+.subtle-regular { @apply text-[10px] font-normal leading-[13px]; }
+```
+
+**What it does:**
+A comprehensive type scale combining font size, weight, and line height into single utility classes. The naming convention is `{size}-{weight}`.
+
+**Why it exists:**
+Typography often requires coordinated changes to size, weight, and line-height. These utilities ensure consistent combinations across the app.
+
+**Analysis:**
+This is actually a reasonable pattern, though the arbitrary pixel values (`text-[30px]`, `leading-[42px]`) could be replaced with Tailwind's built-in scale for better maintainability.
+
+**What you'd need:**
+Your file already has base styles for `h1`–`h6` in `@layer base`. For additional utility combinations, you could add:
+
+```css
+@layer utilities {
+ /* Using Tailwind's built-in scale instead of arbitrary values */
+ .h1-bold { @apply text-5xl font-bold tracking-tight; }
+ .h2-bold { @apply text-4xl font-bold; }
+ .h2-semibold { @apply text-4xl font-semibold; }
+ .h3-bold { @apply text-3xl font-bold; }
+
+ .body-medium { @apply text-sm font-medium; }
+ .body-semibold { @apply text-sm font-semibold; }
+
+ .small-medium { @apply text-xs font-medium; }
+ .caption { @apply text-xs text-muted-foreground; }
+}
+```
+
+Alternatively, just compose Tailwind utilities directly in your JSX — `text-sm font-medium` is clear and doesn't require custom classes.
+
+---
+
+### 6. Placeholder Styles
+
+```css
+.placeholder { @apply placeholder:text-light-400 dark:placeholder:text-light-500; }
+```
+
+**What it does:**
+Sets consistent placeholder text colour in form inputs across light/dark modes.
+
+**Why it exists:**
+Placeholder text should be visually distinct from actual input text, but still readable. The colour often needs adjustment in dark mode.
+
+**What you'd need:**
+Add to your base layer for global application:
+
+```css
+@layer base {
+ input::placeholder,
+ textarea::placeholder {
+ @apply text-muted-foreground;
+ }
+}
+```
+
+Or apply per-component using Tailwind's placeholder modifier: `placeholder:text-muted-foreground`.
+
+---
+
+### 7. Visual Effects
+
+```css
+.invert-colors { @apply invert dark:invert-0; }
+.shadow-light100_dark100 { @apply shadow-light-100 dark:shadow-dark-100; }
+.shadow-light100_darknone { @apply shadow-light-100 dark:shadow-none; }
+```
+
+**What it does:**
+
+- `invert-colors`: Inverts an element's colours in light mode, restores in dark mode. Useful for black icons that need to be white in dark mode.
+- Shadow utilities: Apply different shadow styles per theme. Shadows often look too harsh in dark mode and need to be softer or removed.
+
+**Why it exists:**
+Icons and shadows frequently need theme-specific treatment that simple colour changes don't address.
+
+**What you'd need:**
+If using icons that need inversion (e.g., black SVGs):
+
+```css
+@layer utilities {
+ .invert-on-light { @apply invert dark:invert-0; }
+ .invert-on-dark { @apply dark:invert; }
+}
+```
+
+For shadows, consider defining shadow values in your theme that work across modes, or use:
+
+```css
+@layer utilities {
+ .shadow-theme {
+ @apply shadow-md dark:shadow-none dark:ring-1 dark:ring-border;
+ }
+}
+```
+
+---
+
+### 8. Gradients
+
+```css
+.primary-gradient {
+ background: linear-gradient(129deg, #ff7000 0%, #e2995f 100%);
+}
+
+.dark-gradient {
+ background: linear-gradient(
+ 232deg,
+ rgba(23, 28, 35, 0.41) 0%,
+ rgba(19, 22, 28, 0.7) 100%
+ );
+}
+
+.light-gradient {
+ background: linear-gradient(
+ 132deg,
+ rgba(247, 249, 255, 0.5) 0%,
+ rgba(229, 237, 255, 0.25) 100%
+ );
+}
+
+.primary-text-gradient {
+ background: linear-gradient(129deg, #ff7000 0%, #e2995f 100%);
+ background-clip: text;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+```
+
+**What it does:**
+
+- `primary-gradient`: Brand gradient for buttons, CTAs, highlights (orange tones)
+- `dark-gradient`: Subtle overlay gradient for dark mode cards/surfaces
+- `light-gradient`: Subtle overlay gradient for light mode
+- `primary-text-gradient`: Applies gradient as text colour (the background shows through transparent text)
+
+**Why it exists:**
+Gradients add visual interest and depth. Brand gradients reinforce identity. The text gradient technique creates eye-catching headings.
+
+**What you'd need:**
+First, define brand colours as CSS variables, then create gradient utilities:
+
+```css
+:root {
+ --brand-orange: #ff7000;
+ --brand-gold: #e2995f;
+}
+
+@layer utilities {
+ .bg-gradient-primary {
+ background: linear-gradient(135deg, var(--brand-orange) 0%, var(--brand-gold) 100%);
+ }
+
+ .bg-gradient-surface {
+ @apply bg-gradient-to-br from-background to-muted/50;
+ }
+
+ .text-gradient-primary {
+ background: linear-gradient(135deg, var(--brand-orange) 0%, var(--brand-gold) 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+ }
+}
+```
+
+---
+
+### 9. Layout Utilities
+
+```css
+.flex-center { @apply flex justify-center items-center; }
+.flex-between { @apply flex justify-between items-center; }
+.flex-start { @apply flex justify-start items-center; }
+```
+
+**What it does:**
+Shorthand utilities for common flexbox patterns:
+
+- `flex-center`: Centre children both horizontally and vertically
+- `flex-between`: Space children to opposite ends, vertically centred
+- `flex-start`: Align children to start, vertically centred
+
+**Why it exists:**
+These three-class combinations (`flex justify-center items-center`) are extremely common. Single utilities reduce markup verbosity.
+
+**What you'd need:**
+These are genuinely useful shortcuts. Add if you find yourself writing these combinations frequently:
+
+```css
+@layer utilities {
+ .flex-center { @apply flex items-center justify-center; }
+ .flex-between { @apply flex items-center justify-between; }
+ .flex-start { @apply flex items-center justify-start; }
+ .flex-end { @apply flex items-center justify-end; }
+
+ /* Inline variant (horizontal only) */
+ .inline-center { @apply inline-flex items-center justify-center; }
+}
+```
+
+---
+
+### 10. Component Utilities
+
+```css
+.card-wrapper {
+ @apply bg-light-900 dark:dark-gradient shadow-light-100 dark:shadow-dark-100;
+}
+
+.btn { @apply bg-light-800 dark:bg-dark-300 !important; }
+.btn-secondary { @apply bg-light-800 dark:bg-dark-400 !important; }
+.btn-tertiary { @apply bg-light-700 dark:bg-dark-300 !important; }
+
+.tab {
+ @apply min-h-full dark:bg-dark-400 bg-light-800 text-light-500
+ dark:data-[state=active]:bg-dark-300 data-[state=active]:bg-primary-100
+ data-[state=active]:text-primary-500 !important;
+}
+```
+
+**What it does:**
+Pre-styled component utilities for cards, buttons, and tabs.
+
+**Why it exists:**
+When not using a component library, these utilities provide consistent component styling without writing full CSS classes for each component.
+
+**Problems with this approach:**
+
+- Heavy use of `!important` to override other styles
+- Tightly coupled to specific colour values
+- Doesn't scale well — you end up with `.btn`, `.btn-secondary`, `.btn-tertiary`, `.btn-ghost`, `.btn-outline`...
+- State management (`:hover`, `:active`, `:disabled`) becomes complex
+
+**What you'd need:**
+With shadcn/ui or similar component libraries, you get actual React components (`