Agent Skill
2/7/2026frontend-skill
Frontend development for real_deal platform using Next.js 14.2, React 18.2, TypeScript 5.3.3, and Tailwind CSS 3.4.3. Use when working on web UI development, creating React components, building pages, integrating with backend APIs, or styling with custom CSS variables.
P
phuhao00
0GitHub Stars
1Views
npx skills add phuhao00/real_deal
SKILL.md
| Name | frontend-skill |
| Description | Frontend development for real_deal platform using Next.js 14.2, React 18.2, TypeScript 5.3.3, and Tailwind CSS 3.4.3. Use when working on web UI development, creating React components, building pages, integrating with backend APIs, or styling with custom CSS variables. |
name: frontend-skill description: Frontend development for real_deal platform using Next.js 14.2, React 18.2, TypeScript 5.3.3, and Tailwind CSS 3.4.3. Use when working on web UI development, creating React components, building pages, integrating with backend APIs, or styling with custom CSS variables.
Frontend Development (Next.js)
Tech Stack
- Framework: Next.js 14.2.4 (App Router)
- UI Library: React 18.2.0
- Language: TypeScript 5.3.3
- Styling: Tailwind CSS 3.4.3 + CSS Variables
- API Client: Custom fetch wrapper
Project Structure
web/
app/
page.tsx # Home page (explore feed)
globals.css # Global styles and theme tokens
layout.tsx # Root layout
bookmarks/ # Bookmarks page
chat/ # Chat interface
companies/ # Company pages
investors/ # Investor pages
jobs/ # Job listings
login/ # Login page
media/ # Media pages
notifications/ # Notifications
post/ # Post creation
profile/ # User profiles
projects/ # Project pages
products/ # Product pages
lib/
api.ts # API client utility
components/
Card.tsx # Simple card component
Composer.tsx # Post composer
FacetFilter.tsx # Search and filter
FeedLayout.tsx # Feed layout wrapper
FeedRow.tsx # Feed row item
Navbar.tsx # Navigation
SidebarNav.tsx # Sidebar navigation
CenterHeader.tsx # Header section
RightSidebar.tsx # Right sidebar
# ... more components
package.json
tsconfig.json
tailwind.config.js
next.config.js
postcss.config.js
Key Patterns
API Client Pattern
// app/lib/api.ts
export const API_BASE = process.env.NEXT_PUBLIC_API_BASE || 'http://localhost:8080'
export async function api<T>(path: string, init?: RequestInit): Promise<T> {
const res = await fetch(`${API_BASE}${path}`, {
cache: 'no-store',
credentials: 'include',
...init
})
if (!res.ok) throw new Error(`api ${path} ${res.status}`)
return res.json()
}
Server Component Pattern (App Router)
// app/page.tsx - Server component
import { api } from './lib/api'
import FeedLayout from '../components/FeedLayout'
import Composer from '../components/Composer'
import FeedRow from '../components/FeedRow'
export default async function Page({ searchParams }: { searchParams?: { q?: string, type?: string, density?: string } }) {
const data = await api<{projects:any[];products:any[];posts:any[];jobs:any[];companies:any[]}>('/api/explore')
const feed = [
...data.projects.map(p=>({ id:p.id, title:p.title, subtitle:p.summary, tags:p.tags })),
...data.products.map(p=>({ id:p.id, title:p.name, subtitle:p.summary, tags:p.tags })),
...data.jobs.map(j=>({ id:j.id, title:j.title, subtitle:`${j.location} · ${j.level} · ${j.salary}`, tags:j.skills }))
]
return (
<FeedLayout trending={data.products} news={data.companies} title="动态">
<Composer />
<div className="divide-y divide-[color:var(--border)]">
{feed.map((f:any)=> (
<FeedRow key={f.id} title={f.title} subtitle={f.subtitle} tags={f.tags} />
))}
</div>
</FeedLayout>
)
}
Component Patterns
Simple Card Component
// components/Card.tsx
export default function Card({ title, subtitle }: { title: string, subtitle?: string }){
return (
<div className="border border-neutral-800 p-4 rounded">
<div className="font-medium">{title}</div>
{subtitle ? <div className="text-sm text-neutral-400">{subtitle}</div> : null}
</div>
)
}
Feed Row Component
// components/FeedRow.tsx
export default function FeedRow({ title, subtitle, tags, dense }: { title: string, subtitle?: string, tags?: string[], dense?: boolean }){
return (
<div className={`px-4 ${dense?'py-2':'py-3'} hover:bg-[color:color-mix(in oklab, var(--accent) 6%, transparent)] transition`}>
<div className={`font-medium ${dense?'text-[15px]':'text-[16px]'}`}>{title}</div>
{subtitle ? <div className={`${dense?'text-[14px]':'text-[15px]'} text-neutral-600 mt-0.5`}>{subtitle}</div> : null}
{tags && tags.length ? <div className="text-[12px] mt-1 tag">{tags.join(', ')}</div> : null}
<div className="mt-2 flex items-center gap-8 interactive-actions">
<button className="flex items-center gap-1 interactive-action" aria-label="评论" type="button">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4v8z"/>
</svg>
</button>
</div>
</div>
)
}
Composer Component
// components/Composer.tsx
export default function Composer(){
return (
<div className="panel border rounded-2xl px-4 py-3 mb-4">
<div className="text-sm text-neutral-600">有什么新鲜事?</div>
<div className="mt-2 flex items-center gap-2">
<input className="flex-1 bg-transparent outline-none text-sm" placeholder="分享你的动态、作品或招聘信息" />
<a href="/post" className="btn-primary px-3 py-1 rounded-full text-sm">发布</a>
</div>
</div>
)
}
Facet Filter Component
// components/FacetFilter.tsx - Client component with hooks
"use client"
import { useRouter, useSearchParams, usePathname } from "next/navigation"
type Facet = { key: string; label: string; options: string[] }
export default function FacetFilter({ facets }: { facets: Facet[] }){
const router = useRouter()
const pathname = usePathname()
const params = useSearchParams()
const setParam = (key: string, values: string[]) => {
const usp = new URLSearchParams(params.toString())
if (values.length) usp.set(key, values.join(',')); else usp.delete(key)
router.push(`${pathname}?${usp.toString()}`)
}
const toggle = (key: string, value: string) => {
const cur = (params.get(key) || '').split(',').filter(Boolean)
const next = cur.includes(value) ? cur.filter(v=>v!==value) : [...cur, value]
setParam(key, next)
}
// ... rest of component
}
Theme & Styling
CSS Variables (in globals.css)
:root {
--bg: 255 255 255;
--fg: 0 0 0;
--border: 240 240 240;
--accent: 0 100 220;
/* ... more tokens */
}
Tailwind Custom Classes
.globals.css:
.btn-primary {
@apply bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700;
}
.panel {
@apply bg-white border rounded-lg p-4;
}
.chip {
@apply px-3 py-1 rounded-full text-sm border;
}
Available Backend APIs
// Explore & Content
GET /api/explore // Get all content (projects, products, posts, jobs, companies)
GET /api/projects // List projects
GET /api/products // List products
GET /api/posts // List posts
GET /api/jobs // List jobs
GET /api/companies/:id // Get company details
// Auth & User
POST /api/login // Login
GET /api/me // Get current user
GET /api/users/:id // Get user profile
// VC/YC Features
GET /api/investors // List investors
GET /api/pitch/:id // Get pitch page
GET /api/deal-room/:id // Get deal room
// Media & Assets
GET /api/media/:id // Get media
GET /api/media-assets // List media assets
// Compliance & Verification
GET /api/company-verifications/:companyId
GET /api/job-compliance/:jobId
GET /api/content-moderation/:id
// Billing & Quota
GET /api/usage // Get usage stats
GET /api/quota // Get quota limits
GET /api/capacity-packs // List capacity packs
GET /api/job-slots // Get job slots
GET /api/charges // List charges
// Notifications
GET /api/inbox // Get inbox
GET /api/notification-preferences // Get preferences
Development Commands
cd web
# Development
npm run dev # Start dev server on :3000
# Production
npm run build # Build for production
npm start # Start production server
# Type checking
npx tsc --noEmit # TypeScript type check
# Linting (if configured)
npm run lint
Common Tasks
Create New Page
# Create page in app directory
touch web/app/your-page/page.tsx
# Example:
export default async function YourPage() {
const data = await api<DataType>('/api/endpoint')
return <div>{/* content */}</div>
}
Create New Component
// Create in components/
// web/components/YourComponent.tsx
export default function YourComponent({ prop1, prop2 }: Props) {
return (
<div className="...">
{/* component content */}
</div>
)
}
Add Interactive State (Client Component)
"use client"
import { useState } from 'react'
export default function InteractiveComponent() {
const [count, setCount] = useState(0)
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
)
}
Handle Authentication
// Login page example (client component)
"use client"
export default function LoginPage() {
const handleLogin = async () => {
await fetch('http://localhost:8080/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ email: 'user@example.com' })
})
window.location.href = '/'
}
return <button onClick={handleLogin}>Login</button>
}
Routing
// App Router file-based routing
app/page.tsx // /
app/login/page.tsx // /login
app/jobs/page.tsx // /jobs
app/companies/[id]/page.tsx // /companies/123
// Dynamic routes with params
export default async function CompanyPage({ params }: { params: { id: string } }) {
const company = await api<Company>(`/api/companies/${params.id}`)
return <div>{company.name}</div>
}
Skills Info
Original Name:frontend-skillAuthor:phuhao00
Download