oneie
Version:
Build apps, websites, and AI agents in English. Zero-interaction setup for AI agents (Claude Code, Cursor, Windsurf). Download to your computer, run in the cloud, deploy to the edge. Open source and free forever.
1,056 lines (811 loc) • 28.1 kB
Markdown
title: Frontend
dimension: connections
category: workflows
tags: ai, frontend, ontology, people, ui
related_dimensions: events, groups, people, things
scope: global
created: 2025-11-03
updated: 2025-11-03
version: 1.0.0
ai_context: |
This document is part of the connections dimension in the workflows category.
Location: one/connections/workflows/frontend.md
Purpose: Documents frontend development workflow
Related dimensions: events, groups, people, things
For AI agents: Read this to understand frontend.
# Frontend Development Workflow
**Version:** 2.0.0
**Status:** Active
**Stack:** Astro 5 + React 19 + shadcn/ui + Tailwind v4
## Overview
This document categorizes all tasks for building Astro websites cloned from `/frontend`, mapping them to the 6-dimension ontology and defining clear workflows for pages, components, styling, and deployment.
## The 6-Dimension Frontend Mapping
Every frontend feature maps to the ontology:
```
┌────────────────────────────────────────────────────────────┐
│ 1. ORGANIZATIONS → Multi-tenant UI │
│ Pages: /app/[orgId]/, /settings/organizations/ │
│ Components: OrgSwitcher, OrgSettings │
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 2. PEOPLE → Auth & Authorization │
│ Pages: /account/*, /signin, /signup │
│ Components: AuthForm, RoleGuard, PermissionsTable │
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 3. THINGS → Entity Management │
│ Pages: /courses/*, /agents/*, /tokens/* │
│ Components: CourseCard, AgentList, TokenDashboard │
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 4. CONNECTIONS → Relationships │
│ Components: FollowersList, ConnectionsGraph, RelatedItems│
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 5. EVENTS → Activity Feeds │
│ Components: ActivityTimeline, EventLog, Analytics │
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 6. KNOWLEDGE → Search & Discovery │
│ Components: SearchBar, RAGInterface, RecommendationFeed │
└────────────────────────────────────────────────────────────┘
```
## Frontend Architecture
### Directory Structure
```
src/
├── pages/ # File-based routing (SSR)
│ ├── index.astro # Landing pages
│ ├── blog/ # Content collection pages
│ ├── app/ # Authenticated app pages
│ ├── account/ # Auth pages
│ └── api/ # API endpoints
├── layouts/ # Page layouts
│ ├── Layout.astro # Main layout
│ ├── Blog.astro # Blog post layout
│ └── AppLayout.astro # App layout
├── components/ # React components
│ ├── ui/ # shadcn/ui components (50+)
│ ├── features/ # Feature-specific components
│ ├── auth/ # Auth components
│ └── app/ # App components
├── content/ # Content collections
│ ├── blog/ # Blog posts (markdown)
│ └── config.ts # Content schemas
├── lib/ # Utilities
├── hooks/ # React hooks
├── stores/ # Nanostores
└── styles/ # Global CSS + Tailwind config
```
### The Three Frontend Layers
```
┌────────────────────────────────────────────────────────┐
│ LAYER 1: PAGES (.astro files) │
│ • File-based routing (src/pages/) │
│ • SSR data fetching in frontmatter │
│ • Static HTML generation │
│ • Pass props to components │
└────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────┐
│ LAYER 2: COMPONENTS (.tsx files) │
│ • React 19 islands architecture │
│ • Selective hydration (client:load) │
│ • Interactive UI elements │
│ • shadcn/ui + Tailwind styling │
└────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────┐
│ LAYER 3: LAYOUTS (.astro files) │
│ • Shared page structure │
│ • SEO meta tags │
│ • Global navigation │
│ • Theme initialization │
└────────────────────────────────────────────────────────┘
```
**Key Frontend Features:**
- ✅ Static site generation with dynamic islands
- ✅ Optimal performance (minimal JavaScript)
- ✅ SEO-friendly server-rendered HTML
- ✅ Progressive enhancement
- ✅ Type-safe with TypeScript
## Page Type Taxonomy
### 1. Landing Pages
**Purpose:** Marketing, education, conversion
**Examples:** `index.astro`, `ontology.astro`, `creators.astro`, `software.astro`
**Structure:**
```astro
import Layout from '@/layouts/Layout.astro';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
<Layout title="Page Title">
<!-- Hero Section -->
<section class="min-h-screen">
<h1>Headline</h1>
<p>Subheadline</p>
<Button>CTA</Button>
</section>
<!-- Features Section -->
<section class="grid grid-cols-3 gap-8">
<Card>Feature 1</Card>
<Card>Feature 2</Card>
<Card>Feature 3</Card>
</section>
</Layout>
```
**Key Patterns:**
- Static generation (`export const prerender = true`)
- USAL animations (`data-usal="fade-up duration-600"`)
- Semantic colors (`bg-background`, `text-foreground`)
- Responsive grids (`grid-cols-1 md:grid-cols-2 lg:grid-cols-3`)
### 2. Blog Pages
**Purpose:** Content collections with search & discovery
**Examples:** `blog/index.astro`, `blog/[...slug].astro`
**Index Pattern:**
```astro
import { getCollection } from 'astro:content';
import { BlogSearch } from '@/components/BlogSearch';
const posts = await getCollection('blog');
const viewMode = Astro.url.searchParams.get('view') || 'list';
<Layout title="Blog">
<BlogSearch client:load posts={posts} viewMode={viewMode} />
</Layout>
```
**Dynamic Page Pattern:**
```astro
import { getCollection } from 'astro:content';
import BlogPost from '@/layouts/Blog.astro';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(entry => ({
params: { slug: entry.slug },
props: { entry },
}));
}
const { entry } = Astro.props;
const { Content, headings } = await entry.render();
<BlogPost entry={entry} headings={headings}>
<Content />
</BlogPost>
```
**Key Patterns:**
- Content collections with Zod schemas
- Static generation with `getStaticPaths()`
- `client:load` for interactive search
- View modes (list/grid) via URL params
### 3. App Pages (Authenticated)
**Purpose:** Real-time authenticated dashboards
**Examples:** `app/index.astro`, `app/courses/[id].astro`
**Pattern:**
```astro
import AppLayout from '@/layouts/AppLayout.astro';
import { ConvexHttpClient } from 'convex/browser';
import { api } from '@/convex/_generated/api';
import { CourseView } from '@/components/features/courses/CourseView';
// SSR: Fetch initial data
const convex = new ConvexHttpClient(import.meta.env.PUBLIC_CONVEX_URL);
const course = await convex.query(api.courses.get, { id: Astro.params.id });
// Check auth (middleware handles redirects)
const session = Astro.locals.session;
<AppLayout title={course.name}>
<CourseView
client:load
courseId={course._id}
initialData={course}
/>
</AppLayout>
```
**Key Patterns:**
- `AppLayout.astro` for authenticated shell
- SSR with `ConvexHttpClient` for initial data
- Real-time updates via `useQuery()` in components
- Middleware handles auth checks
### 4. Account Pages (Auth)
**Purpose:** Sign in, sign up, password reset, settings
**Examples:** `account/signin.astro`, `account/signup.astro`, `account/settings.astro`
**Pattern:**
```astro
import Layout from '@/layouts/Layout.astro';
import { SignInForm } from '@/components/auth/SignInForm';
<Layout title="Sign In">
<div class="max-w-md mx-auto">
<SignInForm client:load />
</div>
</Layout>
```
**Key Patterns:**
- Better Auth integration
- Form validation with React Hook Form
- OAuth providers (GitHub, Google)
- Email verification flow
- 2FA support
### 5. API Routes
**Purpose:** Server-side endpoints
**Examples:** `api/hello.ts`, `rss.xml.ts`
**Pattern:**
```typescript
// src/pages/api/thing.ts
import type { APIRoute } from "astro";
export const GET: APIRoute = async ({ params, request }) => {
return new Response(JSON.stringify({ data: "value" }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
};
```
## Component Type Taxonomy
### 1. UI Components (shadcn/ui)
**Location:** `src/components/ui/`
**Examples:** `button.tsx`, `card.tsx`, `dialog.tsx`, `input.tsx`
**Pattern:**
```tsx
import * as React from "react";
import { cn } from "@/lib/utils";
export const Button = React.forwardRef<
HTMLButtonElement,
React.ButtonHTMLAttributes<HTMLButtonElement>
>(({ className, ...props }, ref) => (
<button
ref={ref}
className={cn(
"rounded-md bg-primary text-primary-foreground px-4 py-2",
className
)}
{...props}
/>
));
Button.displayName = "Button";
```
**Key Patterns:**
- Radix UI primitives
- `cn()` utility for class merging
- `forwardRef` for ref passing
- Semantic color tokens
### 2. Feature Components
**Location:** `src/components/features/[domain]/`
**Examples:** `CourseCard.tsx`, `TokenPurchase.tsx`, `AgentChat.tsx`
**Pattern:**
```tsx
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
interface CourseCardProps {
courseId: string;
title: string;
description: string;
price: number;
onEnroll: (courseId: string) => Promise<void>;
}
export function CourseCard({
courseId,
title,
description,
price,
onEnroll,
}: CourseCardProps) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleEnroll = async () => {
setLoading(true);
setError(null);
try {
await onEnroll(courseId);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to enroll");
} finally {
setLoading(false);
}
};
return (
<Card>
<CardHeader>
<CardTitle>{title}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground mb-4">{description}</p>
<div className="flex items-center justify-between">
<span className="text-2xl font-bold">${price}</span>
<Button onClick={handleEnroll} disabled={loading}>
{loading ? "Enrolling..." : "Enroll Now"}
</Button>
</div>
{error && <p className="text-destructive text-sm mt-2">{error}</p>}
</CardContent>
</Card>
);
}
```
**Key Patterns:**
- ✅ Props-based interface (data passed from parent)
- ✅ Callback handlers for actions
- ✅ Local state for UI (loading, error)
- ✅ shadcn/ui components for consistent styling
- ✅ Type-safe with TypeScript interfaces
### 3. Layout Components
**Location:** `src/layouts/`
**Examples:** `Layout.astro`, `Blog.astro`, `AppLayout.astro`
**Main Layout Pattern:**
```astro
import { Sidebar } from '@/components/Sidebar';
import { Toaster } from '@/components/ui/sonner';
import ThemeInit from '@/components/ThemeInit.astro';
import '../styles/global.css';
interface Props {
title: string;
description?: string;
}
const { title, description } = Astro.props;
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
<meta name="description" content={description} />
<ThemeInit />
</head>
<body class="min-h-screen bg-background">
<Sidebar client:only="react">
<slot />
</Sidebar>
<Toaster client:only="react" />
</body>
</html>
```
## Task Categories
### Task 1: Create New Landing Page
**Steps:**
1. **Map to Ontology**
- Which dimension(s)? (e.g., "Tokens" = THINGS dimension)
- What entities? (e.g., token, creator, transaction)
- What relationships? (e.g., creator → owns → token)
2. **Create Page File**
```bash
touch src/pages/tokens.astro
```
3. **Define Structure**
```astro
---
import Layout from '@/layouts/Layout.astro';
import { Card } from '@/components/ui/card';
---
<Layout title="Tokens">
<section class="hero"><!-- Hero --></section>
<section class="features"><!-- Features --></section>
<section class="cta"><!-- CTA --></section>
</Layout>
```
4. **Add Content**
- Copy patterns from similar pages (e.g., `software.astro`)
- Use semantic colors
- Add USAL animations
- Ensure responsive
5. **Test**
```bash
bun run dev
# Visit http://localhost:4321/tokens
```
### Task 2: Create New Blog Post
**Steps:**
1. **Create Markdown File**
```bash
touch src/content/blog/my-post.md
```
2. **Add Frontmatter**
```markdown
---
title: "My Post Title"
description: "Brief description"
date: 2025-10-11
author: "ONE"
tags: ["tutorial", "agents"]
category: "tutorial"
featured: false
---
# Content here
```
3. **Sync Content Types**
```bash
npx astro sync
```
4. **Preview**
- Visit `/blog` to see in list
- Click to view full post
### Task 3: Create New Feature Component
**Steps:**
1. **Map to Ontology**
- What dimension? (e.g., "Token Purchase" = THINGS + EVENTS)
- What data? (e.g., token entity, purchase event)
- What mutations? (e.g., `api.tokens.purchase`)
2. **Create Component Directory**
```bash
mkdir -p src/components/features/tokens
```
3. **Create Component**
```bash
touch src/components/features/tokens/TokenPurchase.tsx
```
4. **Implement Pattern**
```tsx
import { useMutation } from "convex/react";
import { api } from "@/convex/_generated/api";
import { Button } from "@/components/ui/button";
export function TokenPurchase({ tokenId }) {
const purchase = useMutation(api.tokens.purchase);
return (
<Button onClick={() => purchase({ tokenId, amount: 100 })}>
Purchase
</Button>
);
}
```
5. **Use in Page**
```astro
---
import { TokenPurchase } from '@/components/features/tokens/TokenPurchase';
---
<TokenPurchase client:load tokenId={token._id} />
```
### Task 4: Create New App Page (Authenticated)
**Steps:**
1. **Create Page**
```bash
touch src/pages/app/courses/[id].astro
```
2. **SSR Data Fetch**
```astro
---
import { ConvexHttpClient } from 'convex/browser';
import { api } from '@/convex/_generated/api';
const convex = new ConvexHttpClient(import.meta.env.PUBLIC_CONVEX_URL);
const course = await convex.query(api.courses.get, {
id: Astro.params.id
});
---
```
3. **Add Interactive Component**
```astro
<AppLayout title={course.name}>
<CourseView client:load courseId={course._id} />
</AppLayout>
```
4. **Component with Real-time**
```tsx
export function CourseView({ courseId, initialData }) {
const course = useQuery(api.courses.get, { id: courseId });
return <div>{course?.name || initialData.name}</div>;
}
```
### Task 5: Update Existing Page
**Steps:**
1. **Identify File**
```bash
# Example: Update homepage
open src/pages/index.astro
```
2. **Read Existing Code**
- Understand current structure
- Identify sections to modify
3. **Make Changes**
- Use same patterns as existing code
- Maintain color scheme
- Keep animations consistent
4. **Test Changes**
```bash
bun run dev
```
5. **Build & Deploy**
```bash
bun run build
npx astro check
```
## Common Patterns
### Pattern 1: SSR + Hydration
```astro
// SSR: Fetch data server-side
const data = await fetch('...').then(r => r.json());
<!-- Static HTML rendered server-side -->
<div>{data.title}</div>
<!-- Interactive component hydrated client-side -->
<InteractiveComponent client:load initialData={data} />
```
### Pattern 2: Form Handling
```tsx
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
export function ContactForm({
onSubmit,
}: {
onSubmit: (data: FormData) => Promise<void>;
}) {
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setLoading(true);
const formData = new FormData(e.currentTarget);
const data = {
name: formData.get("name") as string,
email: formData.get("email") as string,
message: formData.get("message") as string,
};
try {
await onSubmit(data);
setSuccess(true);
e.currentTarget.reset();
} catch (error) {
console.error("Form submission failed:", error);
} finally {
setLoading(false);
}
};
if (success) {
return <div className="text-green-600">Message sent successfully!</div>;
}
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<Label htmlFor="name">Name</Label>
<Input id="name" name="name" required />
</div>
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" name="email" type="email" required />
</div>
<div>
<Label htmlFor="message">Message</Label>
<Input id="message" name="message" required />
</div>
<Button type="submit" disabled={loading}>
{loading ? "Sending..." : "Send Message"}
</Button>
</form>
);
}
```
### Pattern 3: Search & Filter
```tsx
export function SearchableList({ items }) {
const [query, setQuery] = useState("");
const filtered = items.filter((item) =>
item.name.toLowerCase().includes(query.toLowerCase())
);
return (
<>
<Input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
{filtered.map((item) => (
<Card key={item.id}>{item.name}</Card>
))}
</>
);
}
```
### Pattern 4: View Mode Toggle
```astro
const view = Astro.url.searchParams.get('view') || 'list';
<div class="flex gap-2">
<a href="?view=list" class={view === 'list' ? 'active' : ''}>
List
</a>
<a href="?view=grid" class={view === 'grid' ? 'active' : ''}>
Grid
</a>
</div>
<div class={view === 'grid' ? 'grid grid-cols-3' : 'flex flex-col'}>
{/* Items */}
</div>
```
## Styling Guidelines
### Semantic Colors
```astro
<!-- CORRECT: Use semantic tokens -->
<div class="bg-background text-foreground border border-border">
<div class="bg-card text-card-foreground">
<button class="bg-primary text-primary-foreground">
Click Me
</button>
</div>
</div>
<!-- AVOID: Hard-coded colors -->
<div class="bg-white text-black border border-gray-200">
...
</div>
```
### Dark Mode
```astro
<!-- Colors automatically switch via CSS variables -->
<div class="bg-background dark:bg-background">
<!-- Same class works in both modes -->
</div>
```
### Responsive Design
```astro
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Mobile-first approach -->
</div>
```
### Animations (USAL)
```astro
<div data-usal="fade-up duration-600 delay-100">
<!-- Animates on scroll -->
</div>
```
## Deployment Workflow
### Local Development
```bash
# Start dev server
bun run dev
# Check TypeScript
npx astro check
# Build for production
bun run build
# Preview build
bun run preview
```
### Production Deploy
```bash
# Build
bun run build
# Deploy to Cloudflare Pages
wrangler pages deploy dist --project-name=astro-shadcn
```
### Environment Variables
```env
# Site configuration
PUBLIC_SITE_URL=https://your-domain.com
# Auth (if using Better Auth)
BETTER_AUTH_SECRET=your-secret-key
BETTER_AUTH_URL=https://your-domain.com
GITHUB_CLIENT_ID=your-github-oauth-id
GITHUB_CLIENT_SECRET=your-github-oauth-secret
GOOGLE_CLIENT_ID=your-google-oauth-id
GOOGLE_CLIENT_SECRET=your-google-oauth-secret
# Email (if using Resend)
RESEND_API_KEY=your-resend-api-key
```
## Quick Reference
### File Locations
| Type | Location | Example |
| ----------------- | -------------------------- | ---------------------- |
| Landing Page | `src/pages/` | `tokens.astro` |
| Blog Post | `src/content/blog/` | `my-post.md` |
| App Page | `src/pages/app/` | `courses/[id].astro` |
| Auth Page | `src/pages/account/` | `signin.astro` |
| Feature Component | `src/components/features/` | `tokens/TokenCard.tsx` |
| UI Component | `src/components/ui/` | `button.tsx` |
| Layout | `src/layouts/` | `AppLayout.astro` |
### Commands
```bash
bun run dev # Start dev server
npx astro sync # Sync content types
npx astro check # TypeScript check
bun run build # Production build
bun test # Run tests
wrangler pages deploy # Deploy to Cloudflare
```
### Key Patterns
- **Hydration:** `client:load` directive for interactive React components
- **Static Generation:** `export const prerender = true`
- **Dynamic Routes:** `getStaticPaths()` for parameterized pages
- **Content Collections:** `getCollection('blog')` for type-safe content
- **SSR Data:** Fetch data in frontmatter, pass as props to components
- **Component Props:** Pass data down, callbacks up
- **Form Handling:** Controlled components with local state
## Next Steps
1. **Clone `/frontend`** to new project directory
2. **Install dependencies** with `bun install`
3. **Map feature to ontology** (6 dimensions: Organizations, People, Things, Connections, Events, Knowledge)
4. **Choose page type:**
- **Landing Pages** - Marketing, static content
- **Blog Pages** - Content collections with search
- **App Pages** - Authenticated, interactive
- **Account Pages** - Auth flows
- **API Routes** - Server-side endpoints
5. **Create pages** in `src/pages/` following patterns above
6. **Create components** in `src/components/features/` with props-based interface
7. **Style with Tailwind** using semantic color tokens
8. **Test locally** with `bun run dev`
9. **Build** with `bun run build`
10. **Deploy** to Cloudflare Pages with `wrangler pages deploy`
**Remember:** Every feature maps to the 6-dimension ontology. If you can't map it, rethink the feature.
## Resources & References
### Core Documentation
**6-Dimension Ontology:**
- **[one/knowledge/ontology.md](../ontology.md)** - Complete ontology specification
- 66 thing types, 25 connection types, 67 event types
- Organizations, People, Things, Connections, Events, Knowledge
**Frontend Reference:**
- `/frontend` - Reference implementation
- Astro 5 + React 19 + shadcn/ui + Tailwind v4
- 50+ UI components
- Auth system, blog system
- Content collections
### External Resources
**Astro:**
- https://docs.astro.build/ - Official Astro documentation
- File-based routing
- Content collections
- Server-side rendering
- Islands architecture
**React 19:**
- https://react.dev/ - Official React documentation
- Hooks and state management
- Component patterns
**shadcn/ui:**
- https://ui.shadcn.com/ - Component library
- Built on Radix UI primitives
- Tailwind CSS styling
**Tailwind CSS v4:**
- https://tailwindcss.com/ - Utility-first CSS
- CSS-based configuration
- Dark mode support
## Summary
**ONE Frontend Development Workflow**
**Key Principles:**
1. **6-Dimension Ontology** - Map all features to: Organizations, People, Things, Connections, Events, Knowledge
2. **Islands Architecture** - Static HTML with selective hydration for interactivity
3. **Type Safety** - TypeScript strict mode throughout
4. **Component-Based** - Reusable React components with props-based interface
5. **Performance First** - Minimal JavaScript, optimal loading
**Page Types:**
- **Landing** - Marketing, static, SEO-optimized
- **Blog** - Content collections with search
- **App** - Authenticated, interactive
- **Account** - Auth flows
- **API** - Server-side endpoints
**Result:** Fast, SEO-friendly websites with excellent developer experience and maintainable code.
**ONE platform: Build beautiful, performant frontends with Astro.**