diff --git a/.env.template b/.env.template index 1f58795..7190077 100644 --- a/.env.template +++ b/.env.template @@ -1,11 +1,12 @@ +# Database DATABASE_URL="" -# NextAuth Configuration +# Authentication NEXTAUTH_URL="" NEXTAUTH_SECRET="" AUTH_TRUST_HOST="true" -# GitHub App Configuration (Required for GitHub login) +# GitHub App (required for GitHub login and repository import) GITHUB_APP_ID="" GITHUB_APP_PRIVATE_KEY="" GITHUB_APP_WEBHOOK_SECRET="" @@ -13,31 +14,26 @@ GITHUB_APP_CLIENT_ID="" GITHUB_APP_CLIENT_SECRET="" NEXT_PUBLIC_GITHUB_APP_NAME="" -# GitHub OAuth (DEPRECATED - Use GitHub App instead) -# GITHUB_CLIENT_ID="" -# GITHUB_CLIENT_SECRET="" - -# Sealos OAuth +# Sealos OAuth (optional) SEALOS_JWT_SECRET="" -# job +# Feature Flags +ENABLE_PASSWORD_AUTH="" +ENABLE_GITHUB_AUTH="true" +ENABLE_SEALOS_AUTH="" + +# Reconciliation DATABASE_LOCK_DURATION_SECONDS="" MAX_DATABASES_PER_RECONCILE="" - SANDBOX_LOCK_DURATION_SECONDS="" MAX_SANDBOXES_PER_RECONCILE="" -# k8s resource +# Kubernetes RUNTIME_IMAGE="" -# aiproxy +# AI Proxy AIPROXY_ENDPOINT="" ANTHROPIC_BASE_URL="" -# Log +# Logging LOG_LEVEL="info" - -# login -ENABLE_PASSWORD_AUTH="" -ENABLE_GITHUB_AUTH="true" -ENABLE_SEALOS_AUTH="" diff --git a/.gitignore b/.gitignore index 4355588..51b965d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # dependencies /node_modules +/.pnpm-store/ /.pnp .pnp.* .yarn/* diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index e923c0e..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "recommendations": [ - "dbaeumer.vscode-eslint", - "esbenp.prettier-vscode", - "christian-kohler.npm-intellisense", - "streetsidesoftware.code-spell-checker", - "pomdtr.excalidraw-editor", - "lokalise.i18n-ally", - "stylelint.vscode-stylelint", - "EditorConfig.EditorConfig", - "prisma.prisma" - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 534b113..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - // editor - "editor.formatOnSave": true, - "editor.formatOnType": true, - "editor.tabSize": 2, - "editor.suggestSelection": "first", - "editor.renderControlCharacters": true, - "editor.quickSuggestions": { - "strings": true - }, - "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit" - }, - // eslint - "eslint.format.enable": true, - "eslint.run": "onSave", - "eslint.codeActionsOnSave.mode": "all", - // formatters - "[typescriptreact]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "[typescript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "[json]": { - "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true, - "editor.tabSize": 2, - "editor.insertSpaces": true, - "editor.detectIndentation": false - }, - "typescript.tsdk": "node_modules/typescript/lib", - "cSpell.words": [ - "aiporxy", - "AIPROXY", - "clusterdefinition", - "clusterversion", - "fullstackagent", - "homevn", - "kbcli", - "kubeblocks", - "Kubeconfig", - "NEXTAUTH", - "nsid", - "openebs", - "sealos", - "ttyd", - "whatwg" - ] -} \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 7106215..cda43b4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,154 +1,54 @@ # AGENTS.md -This file provides guidance to Codex (Codex.ai/code) when working with code in this repository. +This file provides guidance to AI agents when working with code in this repository. ## Project Overview -**Fulling v2** is an AI-powered development platform that integrates AI Agent ecosystem to provide full-stack development capabilities. Users can import existing projects from GitHub or create new projects directly on the platform. +**Fulling v3.0** is building **dedicated AI workspaces** — persistent, personalizable environments with skills, files, memory, scripts, and runtime. Think of it as an **out-of-the-box AI toolkit** that users can customize and share. -**Core Value**: Free users' mental bandwidth through AI Agents. Users focus on development while Agents silently handle complex operations (deployment, infrastructure, etc.) without interruption. +Read [docs/architecture.md](./docs/architecture.md) before product or architecture work. It is the source of truth for the v3 workspace model. -**Key Features**: -- **Flexible Project Creation**: Import from GitHub repositories or create new projects from scratch -- **Optional Database**: Add PostgreSQL database on-demand when needed -- **AI Agent Ecosystem**: AI agents handle development, testing, deployment, and infrastructure management -- **Automated Operations**: Deployment, scaling, and infrastructure management happen automatically in the background -- **Full-Stack Development**: Complete environment with optional database, terminal, and file management -- **Zero Infrastructure Knowledge Required**: Users don't need to understand Kubernetes, networking, or DevOps +## Tech Stack -**Architecture**: The platform uses an **asynchronous reconciliation pattern** where API endpoints return immediately and background jobs sync desired state (database) with actual state (Kubernetes) every 3 seconds. +- Next.js 16 (App Router) + React 19 + TypeScript +- Tailwind CSS v4 + Shadcn/UI +- Node.js 22 + Prisma + NextAuth v5 +- Kubernetes + PostgreSQL (KubeBlocks) -## Tech Stack +## Code Conventions -### Frontend -- Framework: Next.js 16 (App Router) + React 19 -- Language: TypeScript -- Styling: Tailwind CSS v4 -- UI Components: Shadcn/UI - -### Backend -- Runtime: Node.js 22 -- API: Next.js API Routes -- Database ORM: Prisma -- Authentication: NextAuth v5 (GitHub, Password, Sealos OAuth) - -### Infrastructure -- Container Orchestration: Kubernetes -- Database: PostgreSQL (via KubeBlocks) -- Web Terminal: ttyd (HTTP Basic Auth) -- File Manager: FileBrowser - -## Key Conventions - -### Code Style -- Use TypeScript strict mode -- Always follow best practices -- Write self-documenting code: for complex functions, describe purpose, expected inputs, and expected outputs above the function -- In `lib/platform/`, prefer one primary action per file. Use noun directories and verb file names, and add a short boundary comment above the main exported function covering purpose, expected inputs/preconditions, expected outputs/guarantees, and what is out of scope. -- Use functional components with hooks - -### Naming Conventions -- K8s resources: `{k8s-project-name}-{resource-type}-{6chars}` -- Environment variables: `UPPER_SNAKE_CASE` -- Database tables: PascalCase (Prisma models) -- API routes: kebab-case -- Files: kebab-case -- In `lib/platform/`, file names should usually be action-oriented verbs such as `create-project-with-sandbox`, `find-installation-repository`, or `get-user-default-namespace`, rather than vague names like `shared` or `helpers`. - -### Component Organization -- **Route-specific components**: Place in `_components/` directory under the route folder - - Use `_` prefix to prevent Next.js from treating it as a route - - Example: `app/(dashboard)/settings/_components/github-status-card.tsx` -- **Shared components**: Place in top-level `components/` directory - - Only for components used across multiple routes - - Example: `components/ui/button.tsx`, `components/sidebar.tsx` - -### Important Patterns - -1. **Always use user-specific K8s service**: - ```typescript - const k8sService = await getK8sServiceForUser(userId) - ``` - -2. **API endpoints are non-blocking**: - - Only update database - - Return immediately - - Reconciliation jobs handle K8s operations - -3. **Use optimistic locking**: - - Repository layer handles locking automatically - - Prevents concurrent updates - -4. **Follow reconciliation pattern**: - - API → Database → Reconciliation Job → Event → K8s Operation - - Status updates happen asynchronously - -## Key Design Decisions - -### Why StatefulSet? -- Persistent storage for each pod -- Stable network identities -- Ordered pod deployment - -### Why Reconciliation Pattern? -- Non-blocking API responses -- Automatic recovery from failures -- Consistent state management -- Easy to monitor and debug - -### Why User-Specific Namespaces? -- Multi-tenancy isolation -- Resource quotas per user -- Separate kubeconfig per user -- No cross-user access - -## Project Structure +- TypeScript strict mode +- Functional components with hooks +- In `lib/platform/`: one primary action per file, noun directories + verb file names, boundary comment above main exported function +- Route-specific components in `_components/` directory +- Shared components in top-level `components/` -``` -Fulling/ -├── app/ # Next.js App Router -│ ├── api/ # API Routes -│ ├── (auth)/ # Auth pages -│ └── (dashboard)/projects/[id]/ -│ └── _components/ # Route-specific components -│ -├── components/ # Shared components -├── hooks/ # Client-side hooks -│ -├── lib/ -│ ├── data/ # Server-side data access (for Server Components) -│ ├── actions/ # Client-side data access (Server Actions) -│ ├── repo/ # Repository layer with optimistic locking -│ ├── services/ # Business logic services -│ ├── events/ # Event bus and listeners -│ ├── jobs/ # Reconciliation background jobs -│ ├── startup/ # Application initialization -│ ├── k8s/ # Kubernetes operations -│ └── util/ # Utility functions -│ -├── prisma/ # Prisma schema -├── provider/ # React Context providers -├── runtime/ # Sandbox Docker image -└── yaml/ # Kubernetes templates -``` +## Current Implementation Context -**Key Directories**: -- `lib/data/` - Server-side data access, used by Server Components -- `lib/actions/` - Server Actions, used by Client Components -- `lib/repo/` - Repository with optimistic locking, used by Jobs/Events -- `lib/events/` + `lib/jobs/` - Core of reconciliation pattern -- `lib/startup/` - Initializes event listeners and reconciliation jobs +- Existing code still contains v2 project/resource abstractions. Do not treat them as v3 product architecture. +- **Asynchronous reconciliation** exists in current code: API → Database → Reconciliation Job → Event → K8s Operation +- **Always use user-specific K8s service**: `const k8sService = await getK8sServiceForUser(userId)` +- **Optimistic locking** in Repository layer +- **Non-blocking APIs**: endpoints only update DB, return immediately -## Documentation Index +## UI Direction -- [Architecture](./docs/architecture.md) - Reconciliation pattern, event system, state management -- [Development Guide](./docs/development.md) - Local development, code patterns, testing -- [Operations Manual](./docs/operations.md) - Deployment, monitoring, K8s operations -- [Troubleshooting](./docs/troubleshooting.md) - Common issues, debugging commands +There is no active v3 design system in the repository. The previous design draft +has been removed. Before substantial UI work, define or confirm the current +visual direction instead of inheriting old visual rules. -## Quick Reference +Avoid generic AI copywriting cliches such as "Elevate", "Seamless", and +"Unleash". + +## Key Files + +- [docs/architecture.md](./docs/architecture.md) — v3 system architecture and product model +- `lib/k8s/k8s-service-helper.ts` — User-specific K8s service +- `lib/events/` + `lib/jobs/` — Reconciliation core +- `instrumentation.ts` — Application startup + +## Development Commands -### Development Commands ```bash pnpm dev # Start dev server pnpm build # Build for production @@ -156,43 +56,3 @@ pnpm lint # Run ESLint npx prisma generate # Generate Prisma client npx prisma db push # Push schema to database ``` - -### Key Files -- `lib/k8s/k8s-service-helper.ts` - User-specific K8s service -- `lib/events/sandbox/sandboxListener.ts` - Sandbox lifecycle handlers -- `lib/jobs/sandbox/sandboxReconcile.ts` - Sandbox reconciliation job -- `lib/events/database/databaseListener.ts` - Database lifecycle handlers -- `lib/jobs/database/databaseReconcile.ts` - Database reconciliation job -- `lib/actions/project.ts` - Project creation (creates Sandbox only) -- `lib/actions/database.ts` - Database creation/deletion (on-demand) -- `prisma/schema.prisma` - Database schema -- `instrumentation.ts` - Application startup - -### Environment Variables -- `DATABASE_URL` - Main app database connection -- `NEXTAUTH_SECRET` - NextAuth secret -- `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` - GitHub OAuth -- `SEALOS_JWT_SECRET` - Sealos OAuth validation -- `RUNTIME_IMAGE` - Container image version - -### Resource Status -- `CREATING` → `STARTING` → `RUNNING` ⇄ `STOPPING` → `STOPPED` -- `UPDATING` - Environment variables being updated -- `TERMINATING` → `TERMINATED` -- `ERROR` - Operation failed - -### Port Exposure -- **3000**: Next.js application -- **7681**: ttyd web terminal -- **8080**: FileBrowser (file manager) - -## Important Notes - -- **Project Resources**: Each project includes a Sandbox (required) and can optionally have a Database (PostgreSQL). Database can be added on-demand after project creation. -- **Reconciliation Delay**: Status updates may take up to 3 seconds -- **User-Specific Namespaces**: Each user operates in their own K8s namespace -- **Frontend Polling**: Client components poll every 3 seconds for status updates -- **Database Wait Time**: PostgreSQL cluster takes 2-3 minutes to reach "Running" (when added) -- **Idempotent Operations**: All K8s methods can be called multiple times safely -- **Lock Duration**: Optimistic locks held for 30 seconds -- **Deployment Domain**: Main app listens on `0.0.0.0:3000` (not localhost) for Sealos diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index d31c8f0..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,196 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -**Fulling v2** is an AI-powered development platform that integrates AI Agent ecosystem to provide full-stack development capabilities. Users can import existing projects from GitHub or create new projects directly on the platform. - -**Core Value**: Free users' mental bandwidth through AI Agents. Users focus on development while Agents silently handle complex operations (deployment, infrastructure, etc.) without interruption. - -**Key Features**: -- **Flexible Project Creation**: Import from GitHub repositories or create new projects from scratch -- **Optional Database**: Add PostgreSQL database on-demand when needed -- **AI Agent Ecosystem**: AI agents handle development, testing, deployment, and infrastructure management -- **Automated Operations**: Deployment, scaling, and infrastructure management happen automatically in the background -- **Full-Stack Development**: Complete environment with optional database, terminal, and file management -- **Zero Infrastructure Knowledge Required**: Users don't need to understand Kubernetes, networking, or DevOps - -**Architecture**: The platform uses an **asynchronous reconciliation pattern** where API endpoints return immediately and background jobs sync desired state (database) with actual state (Kubernetes) every 3 seconds. - -## Tech Stack - -### Frontend -- Framework: Next.js 16 (App Router) + React 19 -- Language: TypeScript -- Styling: Tailwind CSS v4 -- UI Components: Shadcn/UI - -### Backend -- Runtime: Node.js 22 -- API: Next.js API Routes -- Database ORM: Prisma -- Authentication: NextAuth v5 (GitHub, Password, Sealos OAuth) - -### Infrastructure -- Container Orchestration: Kubernetes -- Database: PostgreSQL (via KubeBlocks) -- Web Terminal: ttyd (HTTP Basic Auth) -- File Manager: FileBrowser - -## Key Conventions - -### Code Style -- Use TypeScript strict mode -- Always follow best practices -- Write self-documenting code: for complex functions, describe purpose, expected inputs, and expected outputs above the function -- Use functional components with hooks - -### Naming Conventions -- K8s resources: `{k8s-project-name}-{resource-type}-{6chars}` -- Environment variables: `UPPER_SNAKE_CASE` -- Database tables: PascalCase (Prisma models) -- API routes: kebab-case -- Files: kebab-case - -### Component Organization -- **Route-specific components**: Place in `_components/` directory under the route folder - - Use `_` prefix to prevent Next.js from treating it as a route - - Example: `app/(dashboard)/settings/_components/github-status-card.tsx` -- **Shared components**: Place in top-level `components/` directory - - Only for components used across multiple routes - - Example: `components/ui/button.tsx`, `components/sidebar.tsx` - -### Important Patterns - -1. **Always use user-specific K8s service**: - ```typescript - const k8sService = await getK8sServiceForUser(userId) - ``` - -2. **API endpoints are non-blocking**: - - Only update database - - Return immediately - - Reconciliation jobs handle K8s operations - -3. **Use optimistic locking**: - - Repository layer handles locking automatically - - Prevents concurrent updates - -4. **Follow reconciliation pattern**: - - API → Database → Reconciliation Job → Event → K8s Operation - - Status updates happen asynchronously - -## Key Design Decisions - -### Why StatefulSet? -- Persistent storage for each pod -- Stable network identities -- Ordered pod deployment - -### Why Reconciliation Pattern? -- Non-blocking API responses -- Automatic recovery from failures -- Consistent state management -- Easy to monitor and debug - -### Why User-Specific Namespaces? -- Multi-tenancy isolation -- Resource quotas per user -- Separate kubeconfig per user -- No cross-user access - -## Project Structure - -``` -Fulling/ -├── app/ # Next.js App Router -│ ├── api/ # API Routes -│ ├── (auth)/ # Auth pages -│ └── (dashboard)/projects/[id]/ -│ └── _components/ # Route-specific components -│ -├── components/ # Shared components -├── hooks/ # Client-side hooks -│ -├── lib/ -│ ├── data/ # Server-side data access (for Server Components) -│ ├── actions/ # Client-side data access (Server Actions) -│ ├── repo/ # Repository layer with optimistic locking -│ ├── services/ # Business logic services -│ ├── events/ # Event bus and listeners -│ ├── jobs/ # Reconciliation background jobs -│ ├── startup/ # Application initialization -│ ├── k8s/ # Kubernetes operations -│ └── util/ # Utility functions -│ -├── prisma/ # Prisma schema -├── provider/ # React Context providers -├── runtime/ # Sandbox Docker image -└── yaml/ # Kubernetes templates -``` - -**Key Directories**: -- `lib/data/` - Server-side data access, used by Server Components -- `lib/actions/` - Server Actions, used by Client Components -- `lib/repo/` - Repository with optimistic locking, used by Jobs/Events -- `lib/events/` + `lib/jobs/` - Core of reconciliation pattern -- `lib/startup/` - Initializes event listeners and reconciliation jobs - -## Documentation Index - -- [Architecture](./docs/architecture.md) - Reconciliation pattern, event system, state management -- [Development Guide](./docs/development.md) - Local development, code patterns, testing -- [Operations Manual](./docs/operations.md) - Deployment, monitoring, K8s operations -- [Troubleshooting](./docs/troubleshooting.md) - Common issues, debugging commands - -## Quick Reference - -### Development Commands -```bash -pnpm dev # Start dev server -pnpm build # Build for production -pnpm lint # Run ESLint -npx prisma generate # Generate Prisma client -npx prisma db push # Push schema to database -``` - -### Key Files -- `lib/k8s/k8s-service-helper.ts` - User-specific K8s service -- `lib/events/sandbox/sandboxListener.ts` - Sandbox lifecycle handlers -- `lib/jobs/sandbox/sandboxReconcile.ts` - Sandbox reconciliation job -- `lib/events/database/databaseListener.ts` - Database lifecycle handlers -- `lib/jobs/database/databaseReconcile.ts` - Database reconciliation job -- `lib/actions/project.ts` - Project creation (creates Sandbox only) -- `lib/actions/database.ts` - Database creation/deletion (on-demand) -- `prisma/schema.prisma` - Database schema -- `instrumentation.ts` - Application startup - -### Environment Variables -- `DATABASE_URL` - Main app database connection -- `NEXTAUTH_SECRET` - NextAuth secret -- `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` - GitHub OAuth -- `SEALOS_JWT_SECRET` - Sealos OAuth validation -- `RUNTIME_IMAGE` - Container image version - -### Resource Status -- `CREATING` → `STARTING` → `RUNNING` ⇄ `STOPPING` → `STOPPED` -- `UPDATING` - Environment variables being updated -- `TERMINATING` → `TERMINATED` -- `ERROR` - Operation failed - -### Port Exposure -- **3000**: Next.js application -- **7681**: ttyd web terminal -- **8080**: FileBrowser (file manager) - -## Important Notes - -- **Project Resources**: Each project includes a Sandbox (required) and can optionally have a Database (PostgreSQL). Database can be added on-demand after project creation. -- **Reconciliation Delay**: Status updates may take up to 3 seconds -- **User-Specific Namespaces**: Each user operates in their own K8s namespace -- **Frontend Polling**: Client components poll every 3 seconds for status updates -- **Database Wait Time**: PostgreSQL cluster takes 2-3 minutes to reach "Running" (when added) -- **Idempotent Operations**: All K8s methods can be called multiple times safely -- **Lock Duration**: Optimistic locks held for 30 seconds -- **Deployment Domain**: Main app listens on `0.0.0.0:3000` (not localhost) for Sealos diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ab85ea0..8adffc5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,234 +1,42 @@ -# Contributing to FullStack Agent +# Contributing to Fulling -Thank you for your interest in contributing to FullStack Agent! We welcome contributions from the community and are grateful for any help you can provide. +Thank you for your interest in Fulling. This document covers the essentials for contributing effectively. -## Code of Conduct +## Project Direction -By participating in this project, you agree to abide by our Code of Conduct. Please treat all contributors with respect and professionalism. - -## How to Contribute - -### Reporting Issues - -- Check existing issues before creating a new one -- Use clear, descriptive titles -- Include steps to reproduce the issue -- Provide system information (OS, Node.js version, etc.) -- Include relevant error messages and logs - -### Suggesting Features - -- Check if the feature has already been suggested -- Provide a clear use case -- Explain how it benefits users -- Consider implementation complexity - -### Pull Requests - -1. **Fork the Repository** - ```bash - git clone https://github.com/FullAgent/fulling.git - cd fulling - ``` - -2. **Create a Feature Branch** - ```bash - git checkout -b feature/your-feature-name - ``` - -3. **Make Your Changes** - - Follow the existing code style - - Add tests for new features - - Update documentation as needed - -4. **Test Your Changes** - ```bash - pnpm test - pnpm run lint - ``` - -5. **Commit Your Changes** - - Use clear, descriptive commit messages - - Follow conventional commit format: - ``` - feat: add new feature - fix: resolve bug in component - docs: update README - style: format code - refactor: restructure module - test: add unit tests - chore: update dependencies - ``` - -6. **Push and Create PR** - ```bash - git push origin feature/your-feature-name - ``` - - Create pull request on GitHub - - Link related issues - - Provide detailed description +Fulling v3.0 is building **dedicated AI workspaces** — persistent, personalizable environments with skills, files, memory, scripts, and runtime. Before contributing, read [README.md](./README.md) for the product vision and [design/DESIGN.md](./design/DESIGN.md) for the UI design system. ## Development Setup -### Prerequisites -- Node.js 20.x or higher -- PostgreSQL database -- Kubernetes cluster access +Prerequisites: Node.js 22.12.0+, pnpm 10.20.0+, PostgreSQL, Kubernetes with KubeBlocks. -### Local Development ```bash -# Install dependencies +git clone https://github.com/FullAgent/fulling.git cd fulling -npm install - -# Set up environment -cp .env.example .env.local +pnpm install +cp .env.template .env.local # Edit .env.local with your settings - -# Run database migrations npx prisma generate npx prisma db push - -# Start development server -npm run dev -``` - -## Code Style Guidelines - -### TypeScript -- Use TypeScript for all new code -- Enable strict mode -- Properly type all functions and variables -- Avoid `any` type unless absolutely necessary - -### React Components -- Use functional components with hooks -- Keep components small and focused -- Extract reusable logic into custom hooks -- Use proper prop types - -### File Organization -``` -components/ - ComponentName/ - index.tsx # Component implementation - styles.module.css # Component styles (if needed) - types.ts # Type definitions - utils.ts # Helper functions +pnpm dev ``` -### Naming Conventions -- **Files**: kebab-case (`user-profile.tsx`) -- **Components**: PascalCase (`UserProfile`) -- **Functions**: camelCase (`getUserData`) -- **Constants**: UPPER_SNAKE_CASE (`MAX_RETRIES`) -- **CSS Classes**: kebab-case (`user-profile-card`) - -## Testing - -### Unit Tests -```typescript -// Example test file: component.test.tsx -import { render, screen } from '@testing-library/react'; -import { Component } from './component'; - -describe('Component', () => { - it('renders correctly', () => { - render(); - expect(screen.getByText('Expected Text')).toBeInTheDocument(); - }); -}); -``` - -### Integration Tests -- Test API endpoints -- Test database operations -- Test Kubernetes service methods - -### E2E Tests -- Test critical user flows -- Test authentication -- Test sandbox creation - -## Documentation - -### Code Documentation -- Add JSDoc comments for functions -- Document complex logic -- Include examples where helpful - -```typescript -/** - * Creates a new sandbox for the specified project - * @param projectId - The project identifier - * @param envVars - Environment variables to inject - * @returns Promise - Sandbox details including URLs - * @throws {Error} If project doesn't exist or user lacks permission - */ -async function createSandbox( - projectId: string, - envVars: Record -): Promise { - // Implementation -} -``` - -### README Updates -- Update README for new features -- Keep installation steps current -- Update API documentation - -## Review Process - -### What We Look For -- **Code Quality**: Clean, readable, maintainable -- **Testing**: Adequate test coverage -- **Documentation**: Clear comments and docs -- **Performance**: No unnecessary overhead -- **Security**: No security vulnerabilities - -### Review Timeline -- Initial review within 3-5 days -- Follow-up reviews within 2-3 days -- Merge after approval from maintainer - -## Release Process - -### Version Numbering -We follow Semantic Versioning (SemVer): -- **Major**: Breaking changes -- **Minor**: New features (backward compatible) -- **Patch**: Bug fixes - -### Release Steps -1. Update version in package.json -2. Update CHANGELOG.md -3. Create release tag -4. Deploy to production - -## Getting Help - -### Resources -- [Documentation](https://github.com/FullAgent/fulling/wiki) -- [Issue Tracker](https://github.com/FullAgent/fulling/issues) -- [Discussions](https://github.com/FullAgent/fulling/discussions) - -### Contact -- GitHub Issues for bugs and features -- Discussions for questions and ideas -- Email: contribute@fullstackagent.dev +Generated repository documentation lives in [.qoder/repowiki](./.qoder/repowiki). +Regenerate it when code structure changes materially. -## Recognition +## Before Submitting -Contributors will be: -- Listed in CONTRIBUTORS.md -- Mentioned in release notes -- Given credit in documentation +- [ ] `pnpm lint` passes +- [ ] `pnpm build` succeeds +- [ ] UI changes follow [design/DESIGN.md](./design/DESIGN.md) +- [ ] Commits use conventional format: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` -## License +## Reporting Issues -By contributing, you agree that your contributions will be licensed under the MIT License. +- Search existing issues first +- One issue per bug or feature request +- Include: reproduction steps, expected vs actual behavior, environment info ---- +## Questions? -Thank you for contributing to FullStack Agent! Your efforts help make AI-powered development accessible to everyone. \ No newline at end of file +Open a [GitHub Discussion](https://github.com/FullAgent/fulling/discussions) or ask in an existing issue. diff --git a/README.md b/README.md index e2b89fd..675f3e4 100644 --- a/README.md +++ b/README.md @@ -1,229 +1,169 @@ -# Fulling - AI-Powered Full-Stack Development Platform +# Fulling
- Version 2.0.0-dev - Next.js - TypeScript - PostgreSQL - Kubernetes - Claude Code + Fulling + +

Package AI workspaces once. Share them with people who just need the AI to work.

+ +

+ Fulling v3.0 workspace delivery + Fulling v2.0.0 released + Next.js 16 + TypeScript 5 +

+ +

+ Overview • + Workspace model • + How it works • + Project status • + Local development +

-> [!CAUTION] -> **v2 development in progress** -> -> We're rearchitecting Fulling as an Agentic app. Breaking changes expected. -> -> For stable, use [`v1.0.0`](https://github.com/FullAgent/fulling/tree/v1.0.0). - -## What is Fulling? - -**Fulling lets you focus on coding. AI handles everything else.** - -Import your project from GitHub or start fresh. Claude Code is your AI pair programmer—it writes code, runs tests, manages databases, and deploys to production. All in a browser-based development environment. - -**Configuration-driven development.** Need Stripe? OAuth? Just enter your API keys in project settings. Services become instantly available—no SDK setup, no environment variables, no integration code. Claude Code reads your config and implements the features for you. - ## Overview -Fulling provides a sandboxed environment with Claude Code and PostgreSQL — everything you need to vibe code full-stack apps. - -Fulling automatically sets up everything you need, ready in a minute: -- AI pair programmer (Claude Code) -- Full-stack development environment -- Dedicated database (PostgreSQL) -- Web terminal & file manager -- Live HTTPS domains - -![fulling-frame](https://github.com/user-attachments/assets/5b535c93-8bf0-4014-8984-ef835d548dbc) - -![fulling-desktop](https://github.com/user-attachments/assets/91b40df8-79de-4922-8627-822b98768915) - -### Features +Fulling is a product for creating ready-to-use AI workspaces. + +It is built around a practical problem: many professionals can benefit from AI, +but they do not want to configure skills, prompts, memory, scripts, integrations, +or runtime settings. Fulling gives creators a place to assemble those pieces, +then share the finished workspace with the person who needs it. + +> [!NOTE] +> Fulling v3.0 centers on workspace delivery: the setup work happens once, and +> the recipient opens a prepared AI workspace instead of learning the AI stack. + +## Why Fulling? + +Most AI tools start with an empty chat box. That works for people who already +know how to prompt, configure tools, and judge the outputs. It breaks down when +the user is a domain expert who simply needs help with real work. + +Fulling turns that setup into a deliverable: + +- a building designer receives a workspace with drawing review workflows, + project references, and report templates +- a consultant receives a workspace with client materials, analysis scripts, + and reusable delivery formats +- a team receives a workspace with shared context, approved tools, and repeatable + operating routines + +The recipient uses the workspace. The creator owns the configuration. + +## Workspace Model + +An AI workspace combines the context, capabilities, and runtime needed for a +specific person or job. + +| Part | Purpose | +| --- | --- | +| Mission | The job this AI workspace exists to help with | +| Knowledge | Files, notes, examples, references, and domain material | +| Memory | Durable context that can evolve over time | +| Skills | Named capabilities the AI can use | +| Scripts | Repeatable actions for work that needs reliability | +| Runtime | A place where tools, code, and automation can run | +| Sharing | A way to hand the configured workspace to another user | + +## How It Works + +```text +Create + -> choose who the workspace is for + -> describe the work it supports + -> add knowledge and files + -> configure skills, scripts, memory, and runtime + -> test the workspace + -> share it with the recipient + +Use + -> open the prepared workspace + -> ask for work through task-focused entry points + -> review outputs, files, and approvals + -> keep using the same workspace as context grows +``` -- **AI Pair Programmer** - Claude Code is pre-installed and ready. Describe what you want, it writes the code. +## What Fulling Is Not -- **Zero Setup** - Full-stack environment with database, terminal, and file manager. All pre-configured, ready in seconds. +Fulling is not a prompt marketplace, generic chatbot builder, Kubernetes UI, or +DevOps control panel. Those pieces can exist behind the scenes, but the product +is organized around prepared AI workspaces. -- **Web Terminal** - Full Linux terminal in your browser. Run commands, install packages, debug—everything you'd do locally. +## Project Status -- **File Manager** - Drag & drop files, edit code in browser. Large file support built-in. +Fulling v3.0 is the active product direction. The current repository is being +realigned around the workspace delivery model described above. -- **Live Domains** - Your app gets HTTPS URLs instantly. No port forwarding, no ngrok. Just run and share. +The previous v2.0.0 release is available at +[Fulling v2.0.0](https://github.com/FullAgent/fulling/releases/tag/v2.0.0). -- **Configuration-Driven** - Add Stripe, OAuth, or any service by entering API keys in settings. Claude Code reads your config and implements the integration for you. +Active branches: -- **GitHub Integration** - Import repos, push changes, version control. Works like you'd expect. +- `v3.0` for the current product direction +- `release/2.0` for v2 maintenance +- `main` is not the target branch for v3 work -- **One-Click Deploy** - From sandbox to production in one click. No YAML, no CI/CD pipelines. +## Tech Stack -## Built With +| Area | Stack | +| --- | --- | +| App | Next.js 16 App Router, React 19, TypeScript | +| UI | Tailwind CSS v4, Shadcn/UI, Radix UI | +| Data | Prisma, PostgreSQL | +| Auth | NextAuth v5 | +| Runtime | Kubernetes, KubeBlocks PostgreSQL, ttyd, FileBrowser | +| Integrations | GitHub App, sandbox-side commands, AI proxy | +| Testing | Vitest, ESLint | -- **Frontend**: Next.js, React, TypeScript -- **Backend**: Node.js, PostgreSQL -- **Infrastructure**: Kubernetes +## Repository Map -For technical details, see [Architecture Documentation](./docs/architecture.md). +```text +app/ Next.js routes, dashboard, auth, API endpoints +components/ Shared UI and layout components +lib/ Application libraries and service code +prisma/ Database schema and migrations +runtime/ Runtime image and sandbox support files +public/ Static icons and assets +``` -## Installation +## Local Development ### Prerequisites -- Node.js 22.12.0 or higher +- Node.js 22.12.0 or later +- pnpm 10.20.0 - PostgreSQL database - Kubernetes cluster with KubeBlocks installed -- GitHub OAuth application credentials +- GitHub App and OAuth credentials for GitHub integration work -### Environment Setup +### Setup -1. Clone the repository: ```bash git clone https://github.com/FullAgent/fulling.git cd fulling -``` - -2. Install dependencies: -```bash pnpm install -``` - -3. Set up environment variables: - -Copy `.env.template` to `.env.local` and fill in your values: -```bash cp .env.template .env.local -``` - -4. Initialize database: -```bash npx prisma generate npx prisma db push +pnpm dev ``` -5. Run the development server: -```bash -pnpm run dev -``` - -Open [http://localhost:3000](http://localhost:3000) to access the application. - -### Database Schema - -See [Database Documentation](./docs/database.md) for schema details. - -## Deployment - -### Kubernetes Resources - -The platform creates the following Kubernetes resources for each project: +Open [http://localhost:3000](http://localhost:3000). -1. **Database Cluster** (KubeBlocks): - - PostgreSQL 14.8.0 - - 3Gi storage - - Auto-generated credentials +## Useful Commands -2. **Sandbox StatefulSet**: - - Custom fullstack-web-runtime image - - Claude Code CLI pre-installed - - ttyd web terminal (port 7681) - - FileBrowser (port 8080) - - Application port (3000) - -3. **Services & Ingresses**: - - Internal service for pod networking - - HTTPS ingresses with SSL termination - - WebSocket support for terminal - -### Resource Limits - -Default resource allocation per sandbox: -- CPU: 20m request, 2000m limit -- Memory: 25Mi request, 4096Mi limit -- Storage: 10Gi for sandbox, 3Gi for database - -## Development - -### Project Structure - -``` -fulling/ -├── app/ # Next.js App Router pages -│ ├── api/ # API routes -│ ├── projects/ # Project management pages -│ └── layout.tsx # Root layout -├── components/ # React components -│ ├── ui/ # Shadcn/UI components -│ └── terminal/ # Terminal components -├── lib/ # Core libraries -│ ├── k8s/ # Kubernetes managers -│ ├── events/ # Event system -│ ├── jobs/ # Background jobs -│ ├── repo/ # Repository layer -│ └── services/ # Business services -├── prisma/ # Database schema -├── runtime/ # Docker image for sandboxes -└── docs/ # Documentation +```bash +pnpm dev # Start the development server +pnpm build # Generate Prisma client and build for production +pnpm lint # Run ESLint +pnpm test # Run Vitest +pnpm test:watch # Run Vitest in watch mode +npx prisma generate # Generate Prisma client +npx prisma db push # Push schema changes to the database ``` -### Key Services - -- **SandboxManager** (`lib/k8s/sandbox-manager.ts`) - StatefulSet operations -- **DatabaseManager** (`lib/k8s/database-manager.ts`) - KubeBlocks operations -- **Authentication** (`lib/auth.ts`) - Multi-provider OAuth -- **Event Listeners** (`lib/events/`) - Lifecycle handlers - ## Documentation -- [Architecture](./docs/architecture.md) - Reconciliation pattern, event system -- [Development Guide](./docs/development.md) - Local development -- [Operations Manual](./docs/operations.md) - Deployment, monitoring -- [Troubleshooting](./docs/troubleshooting.md) - Common issues - -## Security - -- **Authentication**: Multi-provider OAuth (GitHub, Password, Sealos) -- **Isolation**: Each sandbox runs in user-specific Kubernetes namespace -- **Terminal Auth**: HTTP Basic Auth with URL token injection -- **Secrets Management**: Sensitive data stored in Kubernetes secrets -- **Resource Limits**: Prevents resource exhaustion - -## Contributing - -See [Contributing Guidelines](CONTRIBUTING.md) for details. - -### Development Setup - -1. Fork the repository -2. Create a feature branch -3. Make your changes -4. Run tests: `pnpm test` -5. Submit a pull request - -## License - -MIT License - see [LICENSE](LICENSE). - -See [CHANGELOG.md](CHANGELOG.md) for release history. - -## Acknowledgments - -- [Anthropic](https://www.anthropic.com/) for Claude Code -- [Sealos](https://sealos.io/) for Kubernetes platform -- [ttyd](https://github.com/tsl0922/ttyd) for web terminal -- [FileBrowser](https://github.com/filebrowser/filebrowser) for file management - -## Contact - -- GitHub: [@fanux](https://github.com/fanux) -- Issues: [GitHub Issues](https://github.com/FullAgent/fulling/issues) - -## Star us for latest updates - -![star-demo](https://github.com/user-attachments/assets/bc497e0b-bd23-4ded-a231-1e382d56f92e) - ---- - -
-100% AI-generated code. Prompted by [@fanux](https://github.com/fanux). -
Powered by Claude Code, with models from Anthropic (Sonnet, Opus), Google (Gemini), Zhipu AI (GLM), and Moonshot (Kimi). -
+- [AGENTS.md](./AGENTS.md) - agent guidance for this repository +- [docs/architecture.md](./docs/architecture.md) - v3 system architecture diff --git a/app/(dashboard)/projects/(list)/_components/page-header-with-filter.tsx b/app/(dashboard)/projects/(list)/_components/page-header-with-filter.tsx index 679aad9..37c781f 100644 --- a/app/(dashboard)/projects/(list)/_components/page-header-with-filter.tsx +++ b/app/(dashboard)/projects/(list)/_components/page-header-with-filter.tsx @@ -27,7 +27,7 @@ export function PageHeaderWithFilter({ activeFilter, onFilterChange }: PageHeade My Projects

- Manage and monitor your full stack apps and deployments. + Manage and monitor your full stack project workspaces.

{ - router.push(`/projects/${projectId}/settings`); + router.push(`/projects/${projectId}/environment`); }; return ( diff --git a/app/(dashboard)/projects/(list)/page.tsx b/app/(dashboard)/projects/(list)/page.tsx index 430cbb9..7764b48 100644 --- a/app/(dashboard)/projects/(list)/page.tsx +++ b/app/(dashboard)/projects/(list)/page.tsx @@ -7,7 +7,7 @@ import { HomePageContent } from './_components/home-page-content' export const metadata = { title: 'My Projects | Fulling', - description: 'Manage and monitor your full stack apps and deployments.', + description: 'Manage and monitor your full stack project workspaces.', } export default async function HomePage() { diff --git a/app/(dashboard)/settings/_components/github-status-card.tsx b/app/(dashboard)/settings/_components/github-status-card.tsx index 7c1b5f5..b8207f8 100644 --- a/app/(dashboard)/settings/_components/github-status-card.tsx +++ b/app/(dashboard)/settings/_components/github-status-card.tsx @@ -121,7 +121,7 @@ export function GitHubStatusCard() { What does the GitHub Integration do?

- Connecting to GitHub allows you to sync your project to Fulling, and automatically deploys your production-ready project to Sealos. + Connecting to GitHub allows you to import repositories and keep project source metadata available in Fulling.

{installation ? ( diff --git a/app/(dashboard)/settings/_components/settings-sidebar.tsx b/app/(dashboard)/settings/_components/settings-sidebar.tsx index bb979b2..7015687 100644 --- a/app/(dashboard)/settings/_components/settings-sidebar.tsx +++ b/app/(dashboard)/settings/_components/settings-sidebar.tsx @@ -8,7 +8,6 @@ import { cn } from '@/lib/utils' const menuItems = [ { label: 'Integrations', href: '/settings/integrations' }, - { label: 'Account', href: '/settings/account' }, ] export function SettingsSidebar() { diff --git a/app/(landing)/_components/hero-section.tsx b/app/(landing)/_components/hero-section.tsx index 8d65239..d736bad 100644 --- a/app/(landing)/_components/hero-section.tsx +++ b/app/(landing)/_components/hero-section.tsx @@ -45,7 +45,7 @@ export function HeroSection({ {/* Subtitle */}

Import an existing repo or start from scratch. Agents set up the workspace, runtime, - database, and deployment in the background. + optional database, and project automation in the background.

{/* Error message */} @@ -109,7 +109,7 @@ const FEATURES_JSX = (
- Agents handle deploy, runtime, and infra automatically + Agents handle runtime and project setup automatically
); diff --git a/app/(landing)/_components/landing-client.tsx b/app/(landing)/_components/landing-client.tsx index 3480da8..50f522d 100644 --- a/app/(landing)/_components/landing-client.tsx +++ b/app/(landing)/_components/landing-client.tsx @@ -21,7 +21,7 @@ interface LandingClientProps { * Handles all interactive logic (auth, navigation) while receiving * server-fetched data (starCount) as props. * - * Authentication Flow (v2.0.0-alpha-3): + * Authentication Flow (v2.0.0): * - Sealos environment: Auto-trigger auth on page load if unauthenticated * - Non-Sealos + Authenticated: Show "Go to Projects" button * - Non-Sealos + Unauthenticated: Show "Start Building Now" → /login diff --git a/app/(landing)/_components/terminal-demo.tsx b/app/(landing)/_components/terminal-demo.tsx index 56d463e..fb1a4db 100644 --- a/app/(landing)/_components/terminal-demo.tsx +++ b/app/(landing)/_components/terminal-demo.tsx @@ -47,7 +47,7 @@ export function TerminalDemo() { Provisioning PostgreSQL cluster...
- Wiring runtime and deployment... + Wiring runtime and project config...
@@ -61,7 +61,7 @@ export function TerminalDemo() { - +
@@ -73,7 +73,7 @@ export function TerminalDemo() {
- +
{/* Success Card */} diff --git a/app/layout.tsx b/app/layout.tsx index a7243f1..cf94dd4 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -20,8 +20,8 @@ const notoSans = Noto_Sans({ export const metadata: Metadata = { title: 'Fulling - AI-Powered Full-Stack Development', - description: 'Create, develop, and deploy production-ready web applications using natural language. Powered by ' + - 'Claude Code in isolated sandbox environments.', + description: + 'Create or import full-stack projects in isolated browser sandboxes powered by Claude Code.', }; export default function RootLayout({ diff --git a/components/MatrixRain.tsx b/components/MatrixRain.tsx deleted file mode 100644 index 6cff39a..0000000 --- a/components/MatrixRain.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import React, { useEffect, useRef } from 'react'; - -export const MatrixRain: React.FC = () => { - const canvasRef = useRef(null); - - useEffect(() => { - const canvas = canvasRef.current; - if (!canvas) return; - - const ctx = canvas.getContext('2d'); - if (!ctx) return; - - let width = canvas.parentElement?.clientWidth || window.innerWidth; - let height = canvas.parentElement?.clientHeight || window.innerHeight; - - // Set canvas size to match parent - canvas.width = width; - canvas.height = height; - - // Configuration - const fontSize = 14; - const columns = Math.ceil(width / fontSize); - const drops: number[] = new Array(columns).fill(1); - - // VS Code-ish palette for the rain - // Using a mix of green (comments), blue (keywords), and generic code colors - const colors = ['#6a9955', '#dcdcaa']; - - // Characters: Katakana + Numbers + Operators + FULLING - const chars = "アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン1234567890<>{}[];:+-*/FULLING"; - const targetWord = "FULLING"; - - // Track sequence progress for each column. -1 means no sequence active. - const sequences: number[] = new Array(columns).fill(-1); - - const draw = () => { - // Create fade effect - // Use the VS Code background color (#1e1e1e) with high transparency - ctx.fillStyle = 'rgba(30, 30, 30, 0.05)'; - ctx.shadowBlur = 0; // Reset shadow to prevent it affecting the background fade - ctx.fillRect(0, 0, width, height); - - ctx.font = `${fontSize}px 'Consolas', 'Monaco', monospace`; - - for (let i = 0; i < drops.length; i++) { - let text = ''; - let isTarget = false; - - // Logic for "FULLING" sequence - if (sequences[i] >= 0) { - // We are in a sequence - text = targetWord[sequences[i]]; - isTarget = true; - sequences[i]++; - if (sequences[i] >= targetWord.length) { - sequences[i] = -1; // Sequence complete - } - } else { - // Random character - text = chars[Math.floor(Math.random() * chars.length)]; - - // Chance to start a sequence - // Adjust probability as needed. 0.005 is 0.5% chance per frame per column. - if (Math.random() < 0.005) { - sequences[i] = 0; - } - } - - // Pick a random color from our palette to make it look like syntax highlighted code - if (isTarget) { - ctx.fillStyle = '#ffffff'; // Bright white for the target word - ctx.shadowColor = '#ffffff'; - ctx.shadowBlur = 8; - } else { - ctx.fillStyle = colors[Math.floor(Math.random() * colors.length)]; - ctx.shadowBlur = 0; - } - - // Draw the character - ctx.fillText(text, i * fontSize, drops[i] * fontSize); - - // Reset drop to top randomly after it has crossed the screen - // Randomness ensures drops don't fall in a perfect line - if (drops[i] * fontSize > height && Math.random() > 0.975) { - drops[i] = 0; - sequences[i] = -1; // Reset sequence if drop resets - } - - drops[i]++; - } - }; - - const intervalId = setInterval(draw, 33); // ~30FPS - - const handleResize = () => { - width = canvas.parentElement?.clientWidth || window.innerWidth; - height = canvas.parentElement?.clientHeight || window.innerHeight; - canvas.width = width; - canvas.height = height; - - // Reset drops on resize to avoid gaps - const newColumns = Math.ceil(width / fontSize); - // Preserve existing drops if possible, or extend - if (newColumns > drops.length) { - const added = new Array(newColumns - drops.length).fill(1); - drops.push(...added); - } - }; - - window.addEventListener('resize', handleResize); - - return () => { - clearInterval(intervalId); - window.removeEventListener('resize', handleResize); - }; - }, []); - - return ( - - ); -}; \ No newline at end of file diff --git a/components/home-page.tsx b/components/home-page.tsx index b23f608..91e8bde 100644 --- a/components/home-page.tsx +++ b/components/home-page.tsx @@ -6,7 +6,6 @@ import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { useSession } from 'next-auth/react'; -import { MatrixRain } from '@/components/MatrixRain'; import { Button } from '@/components/ui/button'; import { authenticateWithSealos } from '@/lib/actions/sealos-auth'; import { useSealos } from '@/provider/sealos'; @@ -85,9 +84,6 @@ export function HomePage() { <> {/* Base marketing page - always visible */}
- {/* Matrix Background Effect */} - -
{/* Hero Section: Logo and Title */} diff --git a/components/sidebar.tsx b/components/sidebar.tsx index e99d9bb..18691ae 100644 --- a/components/sidebar.tsx +++ b/components/sidebar.tsx @@ -2,10 +2,7 @@ import { FaGithub } from 'react-icons/fa6' import { - MdDashboardCustomize, - MdExtension, MdGridView, - MdHub, MdLightbulbOutline, MdPsychology, MdSettings, @@ -15,17 +12,12 @@ import Link from 'next/link' import { usePathname } from 'next/navigation' import { Button } from '@/components/ui/button' -import { Separator } from '@/components/ui/separator' import packageInfo from '../package.json' const menuItems = [ { icon: MdGridView, label: 'Projects', href: '/projects', active: false }, { icon: MdPsychology, label: 'Skills', href: '/skills', active: false }, - { icon: MdHub, label: 'MCP', href: '/mcp', active: false }, - { divider: true }, - { icon: MdDashboardCustomize, label: 'Templates', href: '/templates', active: false }, - { icon: MdExtension, label: 'Integrations', href: '/integrations', active: false }, { icon: MdSettings, label: 'Settings', href: '/settings', active: false }, ] @@ -68,11 +60,7 @@ function NavMenu() { return (