chore: save current workspace changes
This commit is contained in:
@@ -0,0 +1,51 @@
|
|||||||
|
# Agent Instructions
|
||||||
|
|
||||||
|
Use documentation selectively.
|
||||||
|
|
||||||
|
Always read the minimum relevant documentation before making changes.
|
||||||
|
|
||||||
|
## Required documentation by task type
|
||||||
|
|
||||||
|
### Small scoped changes
|
||||||
|
For small UI fixes, copy updates, styling adjustments, or isolated bug fixes:
|
||||||
|
- read only the directly relevant files
|
||||||
|
- do not read project-wide documentation unless needed
|
||||||
|
|
||||||
|
### Feature-scoped changes
|
||||||
|
For changes affecting an existing feature:
|
||||||
|
- read the matching file in `specs/`
|
||||||
|
- read `docs/ARCHITECTURE.md` only if the change affects structure or flow
|
||||||
|
|
||||||
|
### Large or cross-cutting changes
|
||||||
|
For new features, architecture changes, domain rule changes, or public behavior changes:
|
||||||
|
- read:
|
||||||
|
- docs/ARCHITECTURE.md
|
||||||
|
- docs/DOMAIN_RULES.md
|
||||||
|
- docs/FEATURES.md
|
||||||
|
- also read the matching file in `specs/` when applicable
|
||||||
|
|
||||||
|
## Core rules
|
||||||
|
|
||||||
|
- Do not introduce new patterns, abstractions, or frameworks unless explicitly requested.
|
||||||
|
- Do not refactor unrelated code.
|
||||||
|
- Do not rename files, folders, database fields, or public interfaces unless explicitly requested.
|
||||||
|
- Follow the existing folder structure and module boundaries.
|
||||||
|
- Keep changes minimal, scoped, and consistent with the current codebase.
|
||||||
|
- Reuse existing primitives, services, validators, helpers, and utilities whenever possible.
|
||||||
|
- Preserve the current implementation unless the task explicitly requires changing it.
|
||||||
|
|
||||||
|
## Documentation updates
|
||||||
|
|
||||||
|
Update documentation only when implementation changes affect:
|
||||||
|
- feature scope
|
||||||
|
- business rules
|
||||||
|
- architectureڑڑ
|
||||||
|
- public behavior
|
||||||
|
|
||||||
|
Do not update documentation for small isolated fixes or purely visual changes.
|
||||||
|
|
||||||
|
Update only the relevant files in:
|
||||||
|
- docs/
|
||||||
|
- specs/
|
||||||
|
|
||||||
|
Keep documentation aligned with the real implementation, not assumptions.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY
|
||||||
|
version = 1
|
||||||
|
name = "mohfarawati"
|
||||||
|
|
||||||
|
[setup]
|
||||||
|
script = ""
|
||||||
|
|
||||||
|
[[actions]]
|
||||||
|
name = "Run"
|
||||||
|
icon = "run"
|
||||||
|
command = "make restart"
|
||||||
@@ -1,246 +1,145 @@
|
|||||||
---
|
---
|
||||||
name: mohfarawati-frontend-system
|
name: mohfarawati-ui-rules
|
||||||
description: Enforce the project's frontend architecture and UI system when implementing or modifying frontend code.
|
description: Enforce the project's frontend architecture and UI system when implementing or modifying frontend code.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Frontend System
|
# Frontend System
|
||||||
|
|
||||||
This skill ensures that all frontend work follows the established UI architecture and design system used in this project.
|
All frontend work must follow the existing UI architecture and design system implemented in this repository.
|
||||||
|
|
||||||
The system is defined by the real implementation in the codebase, not by external design assumptions.
|
The system is defined by the **actual implementation**, not by external assumptions.
|
||||||
|
|
||||||
## Source of truth
|
## Source of truth
|
||||||
|
|
||||||
The current system is defined by:
|
The UI system is defined by:
|
||||||
|
|
||||||
- `docs/frontend-system-current-state.md`
|
- docs/frontend-system-current-state.md
|
||||||
- `components/ui/*`
|
- components/ui/*
|
||||||
- `components/layout/*`
|
- components/layout/*
|
||||||
- `lib/utils.ts`
|
- lib/utils.ts
|
||||||
- `app/globals.css`
|
- app/globals.css
|
||||||
- `tailwind.config.ts`
|
- tailwind.config.ts
|
||||||
|
|
||||||
These files define the project's UI primitives, tokens, layout rules, and styling system.
|
Always inspect these files before implementing UI.
|
||||||
|
|
||||||
## Primitive architecture
|
---
|
||||||
|
|
||||||
All shared UI must originate from the local primitive layer.
|
# UI primitives
|
||||||
|
|
||||||
Primary primitives live in:
|
Shared UI components must originate from the local primitive layer:
|
||||||
|
|
||||||
`components/ui`
|
`components/ui`
|
||||||
|
|
||||||
Examples include:
|
Examples include:
|
||||||
|
|
||||||
- Button
|
Button, Card, AppCard, Input, Textarea, Select, Dialog, Sheet, Tabs, DropdownMenu, Accordion, Badge, Checkbox, Table, Label, Separator.
|
||||||
- Card
|
|
||||||
- AppCard
|
|
||||||
- Input
|
|
||||||
- Textarea
|
|
||||||
- Select
|
|
||||||
- Dialog
|
|
||||||
- Sheet
|
|
||||||
- Tabs
|
|
||||||
- DropdownMenu
|
|
||||||
- Accordion
|
|
||||||
- Badge
|
|
||||||
- Checkbox
|
|
||||||
- Table
|
|
||||||
- Label
|
|
||||||
- Separator
|
|
||||||
|
|
||||||
Feature code must reuse these primitives rather than reimplementing their behavior.
|
Feature code **must reuse these primitives** instead of reimplementing them.
|
||||||
|
|
||||||
If new shared UI behavior is required, extend the primitive layer instead of bypassing it.
|
If new shared UI behavior is required, extend the primitive layer rather than bypassing it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Styling rules
|
||||||
|
|
||||||
## Class composition
|
## Class composition
|
||||||
|
|
||||||
Use the project's shared helper:
|
Use `cn()` from:
|
||||||
|
|
||||||
`cn()`
|
|
||||||
|
|
||||||
from:
|
|
||||||
|
|
||||||
`lib/utils.ts`
|
`lib/utils.ts`
|
||||||
|
|
||||||
for class composition.
|
Variant logic should use `cva` when primitives support variants.
|
||||||
|
|
||||||
Variant logic should use:
|
## Tokens
|
||||||
|
|
||||||
`class-variance-authority (cva)`
|
Use semantic tokens defined in:
|
||||||
|
|
||||||
when the primitive already exposes variants.
|
|
||||||
|
|
||||||
## Allowed libraries
|
|
||||||
|
|
||||||
Frontend code may use only the libraries already present in the system.
|
|
||||||
|
|
||||||
UI primitives:
|
|
||||||
- `@radix-ui/react-*` through local primitives
|
|
||||||
|
|
||||||
Styling:
|
|
||||||
- `tailwindcss`
|
|
||||||
|
|
||||||
Class composition:
|
|
||||||
- `class-variance-authority`
|
|
||||||
- `clsx`
|
|
||||||
- `tailwind-merge`
|
|
||||||
|
|
||||||
Motion:
|
|
||||||
- `framer-motion`
|
|
||||||
- `tailwindcss-animate`
|
|
||||||
|
|
||||||
Icons:
|
|
||||||
- `lucide-react`
|
|
||||||
|
|
||||||
Do not introduce additional UI frameworks or icon libraries.
|
|
||||||
|
|
||||||
## Token system
|
|
||||||
|
|
||||||
Styling must rely on the semantic token layer defined in:
|
|
||||||
|
|
||||||
- `app/globals.css`
|
- `app/globals.css`
|
||||||
- `tailwind.config.ts`
|
- `tailwind.config.ts`
|
||||||
|
|
||||||
Prefer semantic tokens over raw color values.
|
Prefer tokens over raw values.
|
||||||
|
|
||||||
Shared UI must not introduce new arbitrary color values when tokens already exist.
|
Do not introduce arbitrary colors, radius values, shadows, or borders when tokens already exist.
|
||||||
|
|
||||||
## Radius system
|
---
|
||||||
|
|
||||||
The project uses a shared radius token system.
|
# Allowed libraries
|
||||||
|
|
||||||
Approved radius token categories include:
|
Only use libraries already present in the project.
|
||||||
|
|
||||||
- surface radius
|
UI primitives
|
||||||
- nested element radius
|
- `@radix-ui/react-*` (via local wrappers)
|
||||||
- pill radius
|
|
||||||
|
|
||||||
These tokens are mapped in Tailwind and must be used for shared UI.
|
Styling
|
||||||
|
- `tailwindcss`
|
||||||
|
|
||||||
Shared components should not introduce arbitrary radius values.
|
Utilities
|
||||||
|
- `class-variance-authority`
|
||||||
|
- `clsx`
|
||||||
|
- `tailwind-merge`
|
||||||
|
|
||||||
## Surface and card system
|
Motion
|
||||||
|
- `framer-motion`
|
||||||
|
- `tailwindcss-animate`
|
||||||
|
|
||||||
Shared surfaces should follow the established card system.
|
Icons
|
||||||
|
- `lucide-react`
|
||||||
|
|
||||||
Primary shared surfaces originate from:
|
Do not introduce additional UI frameworks or icon libraries.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Layout and surfaces
|
||||||
|
|
||||||
|
Shared layout and surfaces must reuse existing primitives:
|
||||||
|
|
||||||
- `Card`
|
- `Card`
|
||||||
- `AppCard`
|
- `AppCard`
|
||||||
|
- container components from `components/layout`
|
||||||
|
|
||||||
These primitives define the canonical surface styles used throughout the application.
|
Do not recreate card styles or layout wrappers inside feature code.
|
||||||
|
|
||||||
Feature code should not duplicate card styling directly.
|
---
|
||||||
|
|
||||||
Instead, reuse these primitives or extend them where necessary.
|
# Motion
|
||||||
|
|
||||||
## Layout system
|
Use existing motion patterns.
|
||||||
|
|
||||||
Shared layout constraints should use the project's container system.
|
- custom motion: `framer-motion`
|
||||||
|
- primitive transitions: `tailwindcss-animate`
|
||||||
|
|
||||||
The container primitive defines width limits and horizontal padding behavior.
|
Avoid introducing new motion systems.
|
||||||
|
|
||||||
Container variants include categories such as:
|
---
|
||||||
|
|
||||||
- default layout width
|
# Forbidden patterns
|
||||||
- narrow content width
|
|
||||||
- wide layout width
|
|
||||||
- admin layout width
|
|
||||||
|
|
||||||
Layout code should reuse the container primitive rather than defining ad-hoc layout wrappers.
|
Avoid:
|
||||||
|
|
||||||
## Spacing rhythm
|
- introducing new UI frameworks
|
||||||
|
- bypassing `components/ui` when a primitive already exists
|
||||||
|
- importing Radix primitives directly in feature code
|
||||||
|
- duplicating design systems
|
||||||
|
- creating alternative styling abstractions
|
||||||
|
- hardcoding shared surface styles
|
||||||
|
|
||||||
The project uses a consistent spacing rhythm.
|
---
|
||||||
|
|
||||||
Common spacing categories include:
|
# Arbitrary Tailwind values
|
||||||
|
|
||||||
- surface padding
|
Arbitrary Tailwind values are allowed only for rare layout or typography edge cases.
|
||||||
- component internal spacing
|
|
||||||
- layout gaps
|
|
||||||
- vertical content spacing
|
|
||||||
|
|
||||||
Spacing values should remain consistent with the existing system used in primitives and layout components.
|
They must **not replace tokens** for shared styling (colors, radius, shadows, borders).
|
||||||
|
|
||||||
Avoid introducing arbitrary spacing values for shared components.
|
---
|
||||||
|
|
||||||
## Motion system
|
# Implementation guidance
|
||||||
|
|
||||||
Motion is implemented through two layers.
|
|
||||||
|
|
||||||
Custom motion:
|
|
||||||
- `framer-motion`
|
|
||||||
|
|
||||||
Primitive state transitions:
|
|
||||||
- `tailwindcss-animate`
|
|
||||||
|
|
||||||
Before introducing new motion patterns, inspect existing motion components and reuse their behavior when possible.
|
|
||||||
|
|
||||||
## Icon system
|
|
||||||
|
|
||||||
The project uses a single icon library:
|
|
||||||
|
|
||||||
- `lucide-react`
|
|
||||||
|
|
||||||
Icons should be imported from this library only.
|
|
||||||
|
|
||||||
Do not introduce additional icon libraries.
|
|
||||||
|
|
||||||
## Arbitrary Tailwind values
|
|
||||||
|
|
||||||
Arbitrary Tailwind values are not globally forbidden.
|
|
||||||
|
|
||||||
They may be used when required for:
|
|
||||||
|
|
||||||
- layout-specific grid definitions
|
|
||||||
- rare content sizing constraints
|
|
||||||
- typography fitting adjustments
|
|
||||||
- one-off layout edge cases not covered by tokens
|
|
||||||
|
|
||||||
However, arbitrary values must not replace the shared token system.
|
|
||||||
|
|
||||||
They should not be used for shared-system styling when project tokens already exist, especially for categories such as:
|
|
||||||
|
|
||||||
- radius
|
|
||||||
- colors
|
|
||||||
- shadows
|
|
||||||
- borders
|
|
||||||
- shared surface styling
|
|
||||||
|
|
||||||
When arbitrary values are used, they should remain narrow in scope and justified by layout or typography needs.
|
|
||||||
|
|
||||||
## Forbidden patterns
|
|
||||||
|
|
||||||
The following patterns must be avoided:
|
|
||||||
|
|
||||||
- introducing a new UI framework
|
|
||||||
- bypassing the local primitive layer when an equivalent primitive already exists
|
|
||||||
- creating feature-level implementations of components that already exist in `components/ui`
|
|
||||||
- importing Radix primitives directly in feature code when a local wrapper exists
|
|
||||||
- introducing raw styling for shared UI surfaces when tokenized styles already exist
|
|
||||||
- creating duplicate design systems
|
|
||||||
- adding styling abstractions that conflict with the existing token system
|
|
||||||
|
|
||||||
## Transitional areas
|
|
||||||
|
|
||||||
Some files still contain transitional visual code.
|
|
||||||
|
|
||||||
These areas must not be treated as canonical UI system references for new work.
|
|
||||||
|
|
||||||
Examples include decorative hero components, experimental visual effects, or legacy route-level styling.
|
|
||||||
|
|
||||||
When implementing new UI, prefer primitives and tokens defined in the main system rather than copying patterns from transitional files.
|
|
||||||
|
|
||||||
## Implementation guidance for Codex
|
|
||||||
|
|
||||||
When implementing frontend code:
|
When implementing frontend code:
|
||||||
|
|
||||||
1. Inspect existing primitives before writing new UI.
|
1. Inspect existing primitives first.
|
||||||
2. Reuse primitives from `components/ui`.
|
2. Reuse components from `components/ui`.
|
||||||
3. Prefer semantic tokens over raw styling.
|
3. Prefer tokens over raw styles.
|
||||||
4. Follow the established radius, surface, spacing, and container systems.
|
4. Follow existing layout and surface patterns.
|
||||||
5. Reuse motion patterns before introducing new ones.
|
5. Reuse motion patterns.
|
||||||
6. Keep new UI aligned with the current frontend architecture.
|
6. Extend primitives instead of bypassing them.
|
||||||
|
|
||||||
If a requested UI does not fit the current primitives, extend the primitive layer rather than bypassing it.
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
display_name: MohFarawati Frontend System
|
display_name: mohfarawati-ui-rules
|
||||||
short_description: Enforce the project's frontend architecture and UI primitives
|
short_description: Enforce the project's frontend architecture and UI primitives
|
||||||
default_prompt: Use $frontend-system when creating, editing, or refactoring frontend UI in this project.
|
default_prompt: Use $frontend-system when creating, editing, or refactoring frontend UI in this project.
|
||||||
@@ -1,16 +1,10 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { ArrowRight, BriefcaseBusiness, GraduationCap, Layers3, MapPin, Sparkles, Wrench } from "lucide-react";
|
|
||||||
import Link from "next/link";
|
|
||||||
import { getTranslations } from "next-intl/server";
|
import { getTranslations } from "next-intl/server";
|
||||||
|
|
||||||
import { Container } from "@/components/layout/container";
|
import { Container } from "@/components/layout/container";
|
||||||
import { PageHero } from "@/components/layout/page-hero";
|
import { PageHero } from "@/components/layout/page-hero";
|
||||||
import { SiteLogo } from "@/components/layout/site-logo";
|
import { AppCard } from "@/components/ui/app-card";
|
||||||
import { MotionFade } from "@/components/motion-fade";
|
import { resolveLocale } from "@/lib/locale";
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { getSiteSettings, getSiteSettingsMediaBindings } from "@/lib/app-config";
|
|
||||||
import { getLocalizedPath, resolveLocale } from "@/lib/locale";
|
|
||||||
import { buildLocalizedMetadata } from "@/lib/metadata";
|
import { buildLocalizedMetadata } from "@/lib/metadata";
|
||||||
|
|
||||||
type AboutPageProps = {
|
type AboutPageProps = {
|
||||||
@@ -30,300 +24,28 @@ export async function generateMetadata({ params }: AboutPageProps): Promise<Meta
|
|||||||
locale: localeKey,
|
locale: localeKey,
|
||||||
pathname: "/about",
|
pathname: "/about",
|
||||||
title: t("title"),
|
title: t("title"),
|
||||||
description: t("intro"),
|
description: t("description"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function AboutPage({ params }: AboutPageProps) {
|
export default async function AboutPage({ params }: AboutPageProps) {
|
||||||
const { locale } = await params;
|
const { locale } = await params;
|
||||||
const localeKey = resolveLocale(locale);
|
const localeKey = resolveLocale(locale);
|
||||||
const [t, siteSettings, mediaBindings] = await Promise.all([
|
const t = await getTranslations({ locale: localeKey, namespace: "aboutPage" });
|
||||||
getTranslations({ locale: localeKey, namespace: "aboutPage" }),
|
|
||||||
getSiteSettings(),
|
|
||||||
getSiteSettingsMediaBindings(),
|
|
||||||
]);
|
|
||||||
const siteName = siteSettings.locales[localeKey].siteName;
|
|
||||||
|
|
||||||
const workItems = [
|
|
||||||
{
|
|
||||||
period: t("workOnePeriod"),
|
|
||||||
role: t("workOneRole"),
|
|
||||||
company: t("workOneCompany"),
|
|
||||||
text: t("workOneText"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
period: t("workTwoPeriod"),
|
|
||||||
role: t("workTwoRole"),
|
|
||||||
company: t("workTwoCompany"),
|
|
||||||
text: t("workTwoText"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
period: t("workThreePeriod"),
|
|
||||||
role: t("workThreeRole"),
|
|
||||||
company: t("workThreeCompany"),
|
|
||||||
text: t("workThreeText"),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const educationItems = [
|
|
||||||
{
|
|
||||||
title: t("educationOneTitle"),
|
|
||||||
place: t("educationOnePlace"),
|
|
||||||
text: t("educationOneText"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("educationTwoTitle"),
|
|
||||||
place: t("educationTwoPlace"),
|
|
||||||
text: t("educationTwoText"),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const skillItems = [t("skillOne"), t("skillTwo"), t("skillThree"), t("skillFour"), t("skillFive"), t("skillSix")];
|
|
||||||
const toolItems = [t("toolOne"), t("toolTwo"), t("toolThree"), t("toolFour")];
|
|
||||||
const focusItems = [t("focusOne"), t("focusTwo"), t("focusThree")];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHero
|
<PageHero
|
||||||
locale={localeKey}
|
locale={localeKey}
|
||||||
badge={t("heroBadge")}
|
badge={t("heroEyebrow")}
|
||||||
title={t("heroTitle")}
|
title={t("title")}
|
||||||
description={t("intro")}
|
description={t("description")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Container className="relative z-10 flex flex-col gap-8 pb-12 lg:pb-16">
|
<Container className="pb-16 lg:pb-20">
|
||||||
<MotionFade delay={0.05}>
|
<AppCard level={3} padding="lg" className="mx-auto max-w-3xl text-center">
|
||||||
<section className="grid gap-8 border-b border-border/70 pb-8 lg:grid-cols-12">
|
<p className="text-lg font-medium text-foreground">{t("placeholder")}</p>
|
||||||
<div className="lg:col-span-9">
|
</AppCard>
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className="border-border/70 bg-background/80 px-3 py-1.5 text-[0.72rem] font-semibold tracking-[0.18em] text-foreground/60"
|
|
||||||
>
|
|
||||||
{t("storyEyebrow")}
|
|
||||||
</Badge>
|
|
||||||
|
|
||||||
<h2 className="mt-5 max-w-[11ch] text-balance text-4xl font-semibold leading-[0.92] tracking-[-0.06em] text-foreground sm:text-5xl lg:text-6xl">
|
|
||||||
{t("storyTitle")}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="mt-6 grid gap-5 lg:grid-cols-[minmax(0,1fr)_minmax(15rem,18rem)]">
|
|
||||||
<div className="space-y-4">
|
|
||||||
<p className="text-sm leading-7 text-muted-foreground sm:text-base">
|
|
||||||
{t("storyTextOne")}
|
|
||||||
</p>
|
|
||||||
<p className="text-sm leading-7 text-muted-foreground sm:text-base">
|
|
||||||
{t("storyTextTwo")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-3">
|
|
||||||
{focusItems.map((item) => (
|
|
||||||
<div key={item} className="rounded-nested border border-border/70 bg-surface-2/70 px-4 py-4 text-sm font-medium leading-6 text-foreground/84">
|
|
||||||
{item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-8 flex flex-wrap gap-3">
|
|
||||||
<Button asChild size="lg" className="min-w-[11rem]">
|
|
||||||
<Link href={getLocalizedPath(localeKey, "/contact")}>
|
|
||||||
{t("primaryCta")}
|
|
||||||
<ArrowRight className="h-4 w-4" />
|
|
||||||
</Link>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
asChild
|
|
||||||
size="lg"
|
|
||||||
variant="outline"
|
|
||||||
className="min-w-[11rem] border-border/80 bg-background/70 hover:bg-background"
|
|
||||||
>
|
|
||||||
<Link href={getLocalizedPath(localeKey, "/portfolio")}>
|
|
||||||
{t("secondaryCta")}
|
|
||||||
</Link>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<aside className="flex flex-col gap-5 lg:col-span-3">
|
|
||||||
<div className="rounded-surface border border-border/70 bg-surface-2/65 p-5">
|
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className="border-border/70 bg-background/80 px-3 py-1.5 text-[0.72rem] font-semibold tracking-[0.18em] text-foreground/60"
|
|
||||||
>
|
|
||||||
{t("snapshotEyebrow")}
|
|
||||||
</Badge>
|
|
||||||
<div className="mt-5 flex items-center justify-between gap-4">
|
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold text-foreground">{t("snapshotTitle")}</h3>
|
|
||||||
<p className="mt-2 text-sm leading-6 text-muted-foreground">{t("snapshotText")}</p>
|
|
||||||
</div>
|
|
||||||
<SiteLogo
|
|
||||||
alt={siteName}
|
|
||||||
priority
|
|
||||||
lightLogoUrl={mediaBindings.siteLogoLight?.url}
|
|
||||||
darkLogoUrl={mediaBindings.siteLogoDark?.url}
|
|
||||||
className="h-10 sm:h-11"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="rounded-surface border border-border/70 bg-background/40 p-5">
|
|
||||||
<div className="flex items-start gap-3">
|
|
||||||
<MapPin className="mt-0.5 h-4 w-4 text-brand-primary" />
|
|
||||||
<div>
|
|
||||||
<p className="text-sm font-semibold text-foreground">{t("locationTitle")}</p>
|
|
||||||
<p className="mt-1 text-sm leading-6 text-muted-foreground">{t("locationText")}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</aside>
|
|
||||||
</section>
|
|
||||||
</MotionFade>
|
|
||||||
|
|
||||||
<MotionFade delay={0.1}>
|
|
||||||
<section className="grid gap-8 border-b border-border/70 pb-8 lg:grid-cols-10">
|
|
||||||
<div className="lg:col-span-4">
|
|
||||||
<div className="flex items-start justify-between gap-4">
|
|
||||||
<div>
|
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className="border-border/70 bg-background/80 px-3 py-1.5 text-[0.72rem] font-semibold tracking-[0.18em] text-foreground/60"
|
|
||||||
>
|
|
||||||
{t("experienceEyebrow")}
|
|
||||||
</Badge>
|
|
||||||
<h2 className="mt-4 text-3xl font-semibold tracking-[-0.04em] text-foreground">
|
|
||||||
{t("experienceTitle")}
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<BriefcaseBusiness className="h-5 w-5 text-brand-primary" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-6 space-y-5">
|
|
||||||
{workItems.map((item, index) => (
|
|
||||||
<div
|
|
||||||
key={`${item.period}-${item.role}`}
|
|
||||||
className={index === 0 ? "" : "border-t border-border/70 pt-5"}
|
|
||||||
>
|
|
||||||
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-foreground/50">
|
|
||||||
{item.period}
|
|
||||||
</p>
|
|
||||||
<h3 className="mt-3 text-lg font-semibold text-foreground">{item.role}</h3>
|
|
||||||
<p className="mt-1 text-sm font-medium text-foreground/72">{item.company}</p>
|
|
||||||
<p className="mt-3 text-sm leading-6 text-muted-foreground">{item.text}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="lg:col-span-6">
|
|
||||||
<div className="flex items-start justify-between gap-4">
|
|
||||||
<div>
|
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className="border-border/70 bg-background/80 px-3 py-1.5 text-[0.72rem] font-semibold tracking-[0.18em] text-foreground/60"
|
|
||||||
>
|
|
||||||
{t("educationEyebrow")}
|
|
||||||
</Badge>
|
|
||||||
<h2 className="mt-4 text-3xl font-semibold tracking-[-0.04em] text-foreground">
|
|
||||||
{t("educationTitle")}
|
|
||||||
</h2>
|
|
||||||
<p className="mt-4 max-w-[34rem] text-sm leading-7 text-muted-foreground">
|
|
||||||
{t("educationIntro")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<GraduationCap className="h-5 w-5 text-brand-primary" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-6 grid gap-6 md:grid-cols-2">
|
|
||||||
{educationItems.map((item) => (
|
|
||||||
<div key={item.title} className="rounded-surface border border-border/70 bg-surface-2/60 p-5">
|
|
||||||
<p className="text-sm font-semibold uppercase tracking-[0.16em] text-foreground/50">
|
|
||||||
{item.place}
|
|
||||||
</p>
|
|
||||||
<h3 className="mt-3 text-xl font-semibold text-foreground">{item.title}</h3>
|
|
||||||
<p className="mt-3 text-sm leading-6 text-muted-foreground">{item.text}</p>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</MotionFade>
|
|
||||||
|
|
||||||
<MotionFade delay={0.15}>
|
|
||||||
<section className="grid gap-8 lg:grid-cols-10">
|
|
||||||
<div className="lg:col-span-6">
|
|
||||||
<div className="flex items-start justify-between gap-4">
|
|
||||||
<div>
|
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className="border-border/70 bg-background/80 px-3 py-1.5 text-[0.72rem] font-semibold tracking-[0.18em] text-foreground/60"
|
|
||||||
>
|
|
||||||
{t("skillsEyebrow")}
|
|
||||||
</Badge>
|
|
||||||
<h2 className="mt-4 text-3xl font-semibold tracking-[-0.04em] text-foreground">
|
|
||||||
{t("skillsTitle")}
|
|
||||||
</h2>
|
|
||||||
<p className="mt-4 max-w-[34rem] text-sm leading-7 text-muted-foreground">
|
|
||||||
{t("skillsIntro")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<Layers3 className="h-5 w-5 text-brand-primary" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-6 flex flex-wrap gap-3">
|
|
||||||
{skillItems.map((item) => (
|
|
||||||
<span
|
|
||||||
key={item}
|
|
||||||
className="inline-flex items-center rounded-pill border border-border/70 bg-surface-2/70 px-4 py-2 text-sm font-medium text-foreground/84"
|
|
||||||
>
|
|
||||||
{item}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="lg:col-span-2">
|
|
||||||
<div className="flex items-center justify-between gap-3">
|
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className="border-border/70 bg-background/80 px-3 py-1.5 text-[0.72rem] font-semibold tracking-[0.18em] text-foreground/60"
|
|
||||||
>
|
|
||||||
{t("toolsEyebrow")}
|
|
||||||
</Badge>
|
|
||||||
<Wrench className="h-4 w-4 text-brand-primary" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-5 space-y-3">
|
|
||||||
{toolItems.map((item) => (
|
|
||||||
<div key={item} className="rounded-surface border border-border/70 bg-surface-2/60 px-4 py-3 text-sm font-medium text-foreground/84">
|
|
||||||
{item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="lg:col-span-2">
|
|
||||||
<div className="flex items-center justify-between gap-3">
|
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className="border-border/70 bg-background/80 px-3 py-1.5 text-[0.72rem] font-semibold tracking-[0.18em] text-foreground/60"
|
|
||||||
>
|
|
||||||
{t("focusEyebrow")}
|
|
||||||
</Badge>
|
|
||||||
<Sparkles className="h-4 w-4 text-brand-primary" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-5 space-y-3">
|
|
||||||
{focusItems.map((item) => (
|
|
||||||
<div key={item} className="rounded-surface border border-border/70 bg-background/40 px-4 py-4 text-sm leading-6 text-foreground/84">
|
|
||||||
{item}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</MotionFade>
|
|
||||||
</Container>
|
</Container>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
+3
-54
@@ -65,60 +65,9 @@
|
|||||||
},
|
},
|
||||||
"aboutPage": {
|
"aboutPage": {
|
||||||
"title": "من أنا",
|
"title": "من أنا",
|
||||||
"heroBadge": "خلّيني عرّفك عليّي",
|
"description": "نظرة مركزة على دراستي، دوري الحالي، ونوع شغل الواجهات الذي أقدمه.",
|
||||||
"heroTitle": "معلومات عني",
|
"heroEyebrow": "من أنا",
|
||||||
"intro": "لمحة سريعة عن خبرتي، دراستي، والمهارات والأدوات التي أستخدمها في شغلي اليومي.",
|
"placeholder": "محتوى صفحة من أنا سينضاف هون قريباً."
|
||||||
"storyEyebrow": "نبذة شخصية",
|
|
||||||
"storyTitle": "أشتغل على بناء حضور رقمي واضح، مرتب، وقابل للنمو.",
|
|
||||||
"storyTextOne": "أنا محمد، أركز على الواجهات، الهوية، وتنظيم التجربة بشكل يخلي المنتج أو الخدمة مفهومة من أول نظرة. أحب الشغل الذي يجمع بين الوضوح البصري والتنفيذ العملي بدون تعقيد زائد.",
|
|
||||||
"storyTextTwo": "هذه الصفحة صارت الآن مهيأة لتعرض قصتي المهنية بشكل مرن: أين عملت، ماذا درست، وما هي المهارات والأدوات التي أعتمد عليها يومياً. كل النصوص الحالية قابلة للتبديل بسهولة لاحقاً.",
|
|
||||||
"focusOne": "أهتم بالوضوح قبل الزخرفة.",
|
|
||||||
"focusTwo": "أفضل الأنظمة القابلة للتوسع والصيانة.",
|
|
||||||
"focusThree": "أشتغل بطريقة مباشرة وسريعة المراجعة.",
|
|
||||||
"primaryCta": "تواصل معي",
|
|
||||||
"secondaryCta": "شوف معرض الأعمال",
|
|
||||||
"snapshotEyebrow": "حالياً",
|
|
||||||
"snapshotTitle": "أبني من برلين",
|
|
||||||
"snapshotText": "أشتغل عن بعد ومع فرق مختلفة، مع تركيز على المواقع، الواجهات، والأنظمة الصغيرة المرنة.",
|
|
||||||
"locationTitle": "القاعدة الحالية",
|
|
||||||
"locationText": "برلين، ألمانيا، مع قابلية للعمل مع فرق محلية أو عن بعد.",
|
|
||||||
"experienceEyebrow": "أين اشتغلت",
|
|
||||||
"experienceTitle": "خبرتي العملية",
|
|
||||||
"workOnePeriod": "2024 - الآن",
|
|
||||||
"workOneRole": "Frontend Developer",
|
|
||||||
"workOneCompany": "استوديو رقمي أو شركة منتج",
|
|
||||||
"workOneText": "مكان مخصص لذكر آخر جهة عمل، طبيعة المسؤوليات، ونوع المشاريع التي اشتغلت عليها.",
|
|
||||||
"workTwoPeriod": "2022 - 2024",
|
|
||||||
"workTwoRole": "UI Designer",
|
|
||||||
"workTwoCompany": "وكالة أو فريق داخلي",
|
|
||||||
"workTwoText": "هنا يمكن ذكر دور سابق يوضح المزج بين التصميم والتنفيذ أو بين البراند والواجهات.",
|
|
||||||
"workThreePeriod": "قبل ذلك",
|
|
||||||
"workThreeRole": "Freelance / Contract Work",
|
|
||||||
"workThreeCompany": "عمل حر أو تعاونات مستقلة",
|
|
||||||
"workThreeText": "خانة مناسبة لإضافة مشاريع خاصة، تعاونات قصيرة، أو مراحل انتقالية مهمة في المسار.",
|
|
||||||
"educationEyebrow": "شو درست",
|
|
||||||
"educationTitle": "الخلفية الدراسية",
|
|
||||||
"educationIntro": "هذا القسم مخصص لوضع الدراسة الأكاديمية أو الدورات المركزة التي أثرت على طريقة التفكير والشغل.",
|
|
||||||
"educationOneTitle": "اسم التخصص أو الشهادة",
|
|
||||||
"educationOnePlace": "اسم الجامعة أو المعهد",
|
|
||||||
"educationOneText": "وصف قصير يوضح ما الذي درسته فعلياً، وكيف انعكس ذلك لاحقاً على شغلك أو على طريقة تحليلك للمشاريع.",
|
|
||||||
"educationTwoTitle": "دورات أو تدريب متخصص",
|
|
||||||
"educationTwoPlace": "منصة أو جهة تدريب",
|
|
||||||
"educationTwoText": "مكان مناسب لذكر أي دراسة مكملة، تدريب عملي، أو برنامج صقل مهارات أخذته لاحقاً.",
|
|
||||||
"skillsEyebrow": "مهاراتي",
|
|
||||||
"skillsTitle": "المهارات التي أركز عليها",
|
|
||||||
"skillsIntro": "كتلة واسعة لعرض المهارات الأساسية التي تريد إظهارها بشكل سريع وواضح وقابل للتحديث.",
|
|
||||||
"skillOne": "تصميم واجهات",
|
|
||||||
"skillTwo": "بناء Design Systems",
|
|
||||||
"skillThree": "Frontend Architecture",
|
|
||||||
"skillFour": "تحويل الأفكار إلى صفحات واضحة",
|
|
||||||
"skillFive": "تنظيم المحتوى والتسلسل البصري",
|
|
||||||
"skillSix": "التعاون السريع مع العملاء والفرق",
|
|
||||||
"toolsEyebrow": "أدواتي",
|
|
||||||
"toolOne": "Figma",
|
|
||||||
"toolTwo": "Next.js",
|
|
||||||
"toolThree": "Tailwind CSS",
|
|
||||||
"toolFour": "WordPress"
|
|
||||||
},
|
},
|
||||||
"contactPage": {
|
"contactPage": {
|
||||||
"title": "تواصل",
|
"title": "تواصل",
|
||||||
|
|||||||
+3
-54
@@ -65,60 +65,9 @@
|
|||||||
},
|
},
|
||||||
"aboutPage": {
|
"aboutPage": {
|
||||||
"title": "Über mich",
|
"title": "Über mich",
|
||||||
"heroBadge": "Mehr über mich",
|
"description": "Ein fokussierter Überblick über meine Ausbildung, meine aktuelle Rolle und die Art von Frontend Arbeit, die ich liefere.",
|
||||||
"heroTitle": "Über mich",
|
"heroEyebrow": "Über mich",
|
||||||
"intro": "Ein schneller Überblick über meine Erfahrung, Ausbildung sowie die Skills und Tools, die ich in der täglichen Arbeit nutze.",
|
"placeholder": "Der Inhalt der About Seite kommt bald hier hin."
|
||||||
"storyEyebrow": "Persönlicher Überblick",
|
|
||||||
"storyTitle": "Ich baue digitale Präsenz, die klar, geordnet und bereit zum Wachsen ist.",
|
|
||||||
"storyTextOne": "Ich bin Mohamad und arbeite mit Fokus auf Interfaces, Identität und klar strukturierte Nutzererlebnisse. Mich interessiert Arbeit, die visuelle Klarheit mit praktischer Umsetzung verbindet.",
|
|
||||||
"storyTextTwo": "Diese Seite ist jetzt so aufgebaut, dass sie meine berufliche Geschichte flexibel zeigen kann: wo ich gearbeitet habe, was ich studiert habe und welche Skills und Tools ich am häufigsten nutze.",
|
|
||||||
"focusOne": "Klarheit vor Dekoration.",
|
|
||||||
"focusTwo": "Systeme, die skalieren und wartbar bleiben.",
|
|
||||||
"focusThree": "Direkte Zusammenarbeit mit schnellen Feedback Schleifen.",
|
|
||||||
"primaryCta": "Kontakt aufnehmen",
|
|
||||||
"secondaryCta": "Portfolio ansehen",
|
|
||||||
"snapshotEyebrow": "Aktuell",
|
|
||||||
"snapshotTitle": "Ich arbeite aus Berlin",
|
|
||||||
"snapshotText": "Ich arbeite remote und mit verteilten Teams, mit Fokus auf Websites, Interfaces und flexible kleine Systeme.",
|
|
||||||
"locationTitle": "Aktueller Standort",
|
|
||||||
"locationText": "Berlin, Deutschland, mit Offenheit für lokale und remote Zusammenarbeit.",
|
|
||||||
"experienceEyebrow": "Wo ich gearbeitet habe",
|
|
||||||
"experienceTitle": "Berufserfahrung",
|
|
||||||
"workOnePeriod": "2024 - heute",
|
|
||||||
"workOneRole": "Frontend Developer",
|
|
||||||
"workOneCompany": "Digital Studio oder Produktfirma",
|
|
||||||
"workOneText": "Hier kann die aktuelle oder letzte Position mit Verantwortung und Projektart eingetragen werden.",
|
|
||||||
"workTwoPeriod": "2022 - 2024",
|
|
||||||
"workTwoRole": "UI Designer",
|
|
||||||
"workTwoCompany": "Agentur oder internes Team",
|
|
||||||
"workTwoText": "Ein früherer Schritt, der die Verbindung zwischen Design und Umsetzung oder zwischen Branding und Interface Arbeit zeigt.",
|
|
||||||
"workThreePeriod": "Davor",
|
|
||||||
"workThreeRole": "Freelance / Contract Work",
|
|
||||||
"workThreeCompany": "Unabhängige Zusammenarbeit",
|
|
||||||
"workThreeText": "Ein guter Platz für freie Projekte, Kooperationen oder wichtige Übergangsphasen im Werdegang.",
|
|
||||||
"educationEyebrow": "Was ich studiert habe",
|
|
||||||
"educationTitle": "Ausbildung und Studium",
|
|
||||||
"educationIntro": "Dieser Bereich ist für Studium oder fokussierte Weiterbildungen gedacht, die meine Denkweise und Arbeitsweise geprägt haben.",
|
|
||||||
"educationOneTitle": "Studiengang oder Abschluss",
|
|
||||||
"educationOnePlace": "Universität oder Institut",
|
|
||||||
"educationOneText": "Eine kurze Beschreibung davon, was ich tatsächlich gelernt habe und wie es später meinen Blick auf Projekte beeinflusst hat.",
|
|
||||||
"educationTwoTitle": "Kurse oder spezialisiertes Training",
|
|
||||||
"educationTwoPlace": "Plattform oder Trainingsanbieter",
|
|
||||||
"educationTwoText": "Ein geeigneter Platz für ergänzende Weiterbildung, praxisnahes Training oder Programme zur Vertiefung meiner Skills.",
|
|
||||||
"skillsEyebrow": "Skills",
|
|
||||||
"skillsTitle": "Worauf ich mich konzentriere",
|
|
||||||
"skillsIntro": "Ein breiter Block für die wichtigsten Fähigkeiten, die schnell, klar und später leicht aktualisierbar gezeigt werden sollen.",
|
|
||||||
"skillOne": "Interface Design",
|
|
||||||
"skillTwo": "Design Systems",
|
|
||||||
"skillThree": "Frontend Architektur",
|
|
||||||
"skillFour": "Ideen in klare Seiten übersetzen",
|
|
||||||
"skillFive": "Content Struktur und visuelle Hierarchie",
|
|
||||||
"skillSix": "Schnelle Zusammenarbeit mit Kunden und Teams",
|
|
||||||
"toolsEyebrow": "Tools",
|
|
||||||
"toolOne": "Figma",
|
|
||||||
"toolTwo": "Next.js",
|
|
||||||
"toolThree": "Tailwind CSS",
|
|
||||||
"toolFour": "WordPress"
|
|
||||||
},
|
},
|
||||||
"contactPage": {
|
"contactPage": {
|
||||||
"title": "Kontakt",
|
"title": "Kontakt",
|
||||||
|
|||||||
+3
-54
@@ -65,60 +65,9 @@
|
|||||||
},
|
},
|
||||||
"aboutPage": {
|
"aboutPage": {
|
||||||
"title": "About",
|
"title": "About",
|
||||||
"heroBadge": "A bit more about me",
|
"description": "A focused overview of my education, current role, and the kind of frontend work I deliver.",
|
||||||
"heroTitle": "About me",
|
"heroEyebrow": "About",
|
||||||
"intro": "A quick overview of my experience, education, and the skills and tools I rely on in day-to-day work.",
|
"placeholder": "About page content will be added here soon."
|
||||||
"storyEyebrow": "Personal overview",
|
|
||||||
"storyTitle": "I build digital presence that is clear, structured, and ready to grow.",
|
|
||||||
"storyTextOne": "I am Mohamad, focused on interfaces, identity, and shaping experiences that feel understandable from the first impression. I like work that connects visual clarity with practical execution.",
|
|
||||||
"storyTextTwo": "This page is now structured to present my professional story in a flexible way: where I worked, what I studied, and which skills and tools I use most often. The copy can be replaced easily later.",
|
|
||||||
"focusOne": "Clarity before decoration.",
|
|
||||||
"focusTwo": "Systems that scale and stay maintainable.",
|
|
||||||
"focusThree": "Direct work with fast review cycles.",
|
|
||||||
"primaryCta": "Contact me",
|
|
||||||
"secondaryCta": "View portfolio",
|
|
||||||
"snapshotEyebrow": "Current",
|
|
||||||
"snapshotTitle": "Building from Berlin",
|
|
||||||
"snapshotText": "I work remotely and with distributed teams, focused on websites, interfaces, and flexible small systems.",
|
|
||||||
"locationTitle": "Current base",
|
|
||||||
"locationText": "Berlin, Germany, with flexibility to work with local and remote teams.",
|
|
||||||
"experienceEyebrow": "Where I worked",
|
|
||||||
"experienceTitle": "Work experience",
|
|
||||||
"workOnePeriod": "2024 - now",
|
|
||||||
"workOneRole": "Frontend Developer",
|
|
||||||
"workOneCompany": "Digital studio or product company",
|
|
||||||
"workOneText": "Use this slot for the latest role, the responsibilities, and the types of projects handled there.",
|
|
||||||
"workTwoPeriod": "2022 - 2024",
|
|
||||||
"workTwoRole": "UI Designer",
|
|
||||||
"workTwoCompany": "Agency or in-house team",
|
|
||||||
"workTwoText": "A previous role that shows the overlap between design and implementation or between branding and interface work.",
|
|
||||||
"workThreePeriod": "Before that",
|
|
||||||
"workThreeRole": "Freelance / Contract Work",
|
|
||||||
"workThreeCompany": "Independent collaborations",
|
|
||||||
"workThreeText": "A good place for personal projects, contract work, or key transition stages in the overall path.",
|
|
||||||
"educationEyebrow": "What I studied",
|
|
||||||
"educationTitle": "Educational background",
|
|
||||||
"educationIntro": "This block is meant for academic study or focused learning tracks that shaped the way I think and work.",
|
|
||||||
"educationOneTitle": "Degree or field of study",
|
|
||||||
"educationOnePlace": "University or institute",
|
|
||||||
"educationOneText": "A short description of what I actually studied and how it later influenced the way I approach projects.",
|
|
||||||
"educationTwoTitle": "Courses or specialized training",
|
|
||||||
"educationTwoPlace": "Platform or training provider",
|
|
||||||
"educationTwoText": "A good place for follow-up learning, hands-on training, or a program that sharpened my skills later on.",
|
|
||||||
"skillsEyebrow": "Skills",
|
|
||||||
"skillsTitle": "Skills I focus on",
|
|
||||||
"skillsIntro": "A wide block for listing the core skills you want to highlight in a quick and update-friendly way.",
|
|
||||||
"skillOne": "Interface design",
|
|
||||||
"skillTwo": "Design systems",
|
|
||||||
"skillThree": "Frontend architecture",
|
|
||||||
"skillFour": "Turning ideas into clear pages",
|
|
||||||
"skillFive": "Content structure and visual hierarchy",
|
|
||||||
"skillSix": "Fast collaboration with clients and teams",
|
|
||||||
"toolsEyebrow": "Tools",
|
|
||||||
"toolOne": "Figma",
|
|
||||||
"toolTwo": "Next.js",
|
|
||||||
"toolThree": "Tailwind CSS",
|
|
||||||
"toolFour": "WordPress"
|
|
||||||
},
|
},
|
||||||
"contactPage": {
|
"contactPage": {
|
||||||
"title": "Contact",
|
"title": "Contact",
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
---
|
|
||||||
name: mohs-frontend-system
|
|
||||||
description: Use this skill for frontend work in Next.js, Tailwind CSS, and shadcn/ui projects, especially when editing pages, layouts, components, styling, or refactoring UI systems. Apply it when Codex needs to keep visual decisions consistent, reuse shared primitives, centralize tokens and layout patterns, and avoid mixed old and new UI approaches.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Mohs Frontend System
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Follow the existing project structure.
|
|
||||||
Reuse shared components before creating new ones.
|
|
||||||
Keep visual decisions global and system-driven instead of scattering them inside page files.
|
|
||||||
|
|
||||||
## Workflow
|
|
||||||
|
|
||||||
1. Inspect the current frontend structure before editing.
|
|
||||||
2. Find existing shared primitives in `components/ui/*` and `components/layout/*`.
|
|
||||||
3. Check global tokens and style rules in `app/globals.css`.
|
|
||||||
4. Check Tailwind mapping in `tailwind.config.ts`.
|
|
||||||
5. Decide whether the change belongs in global styles, shared primitives, or page-level composition.
|
|
||||||
6. Reuse and extend shared patterns instead of introducing one-off classes or duplicated markup.
|
|
||||||
7. Finish the refactor completely. Do not leave mixed patterns behind.
|
|
||||||
|
|
||||||
## System Rules
|
|
||||||
|
|
||||||
- Follow the existing project structure.
|
|
||||||
- Reuse shared components before creating new ones.
|
|
||||||
- Keep visual decisions global, not scattered in page files.
|
|
||||||
- Prefer tokens and shared primitives over repeated raw classes.
|
|
||||||
- Prefer consistency over creativity.
|
|
||||||
- Do not invent random styles, spacing, radius, shadows, or layouts.
|
|
||||||
- Use shadcn/ui as a base only, not as the final design language.
|
|
||||||
- Keep layout primitives shared.
|
|
||||||
- Keep UI primitives shared.
|
|
||||||
- Do not leave old and new patterns mixed together.
|
|
||||||
- Do not leave partial refactors.
|
|
||||||
|
|
||||||
## File Ownership
|
|
||||||
|
|
||||||
- Global styles and tokens: `app/globals.css`
|
|
||||||
- Tailwind mapping: `tailwind.config.ts`
|
|
||||||
- Shared UI: `components/ui/*`
|
|
||||||
- Shared layout: `components/layout/*`
|
|
||||||
|
|
||||||
## Implementation Rules
|
|
||||||
|
|
||||||
- Put reusable visual decisions into shared layers first.
|
|
||||||
- Keep page files focused on composition and data flow.
|
|
||||||
- If a new pattern is needed in more than one place, extract it immediately.
|
|
||||||
- If an old pattern conflicts with the new one, replace the old pattern in the touched area instead of leaving both.
|
|
||||||
- Match the existing code style and naming conventions of the repo.
|
|
||||||
|
|
||||||
## Output Style
|
|
||||||
|
|
||||||
1. Briefly explain the change.
|
|
||||||
2. List files to edit or create.
|
|
||||||
3. Execute the full implementation.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
interface:
|
|
||||||
display_name: "Moh Frontend System"
|
|
||||||
short_description: "Next.js frontend system rules"
|
|
||||||
default_prompt: "Use $mohs-frontend-system to implement or refactor frontend UI consistently in this project."
|
|
||||||
Reference in New Issue
Block a user