awel 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/README.zh-CN.md +8 -0
- package/dist/cli/agent.d.ts +2 -1
- package/dist/cli/agent.js +3 -2
- package/dist/cli/awel-config.d.ts +10 -0
- package/dist/cli/awel-config.js +28 -0
- package/dist/cli/babel-setup.js +2 -19
- package/dist/cli/create.d.ts +1 -0
- package/dist/cli/create.js +136 -0
- package/dist/cli/index.js +60 -4
- package/dist/cli/onboarding.d.ts +1 -0
- package/dist/cli/onboarding.js +58 -0
- package/dist/cli/providers/registry.d.ts +12 -0
- package/dist/cli/providers/registry.js +41 -0
- package/dist/cli/providers/types.d.ts +2 -0
- package/dist/cli/providers/vercel.js +44 -1
- package/dist/cli/proxy.d.ts +1 -1
- package/dist/cli/proxy.js +40 -7
- package/dist/cli/server.d.ts +2 -1
- package/dist/cli/server.js +14 -3
- package/dist/cli/templates/blank/AGENT.md +24 -0
- package/dist/cli/templates/blank/src/app/page.tsx +10 -0
- package/dist/cli/templates/blog/AGENT.md +26 -0
- package/dist/cli/templates/blog/src/app/blog/[slug]/page.tsx +38 -0
- package/dist/cli/templates/blog/src/app/page.tsx +35 -0
- package/dist/cli/templates/blog/src/lib/posts.ts +42 -0
- package/dist/cli/templates/dashboard/AGENT.md +26 -0
- package/dist/cli/templates/dashboard/src/app/layout.tsx +28 -0
- package/dist/cli/templates/dashboard/src/app/page.tsx +30 -0
- package/dist/cli/templates/dashboard/src/components/Sidebar.tsx +31 -0
- package/dist/cli/templates/dashboard/src/components/StatsCard.tsx +24 -0
- package/dist/cli/templates/landing/AGENT.md +26 -0
- package/dist/cli/templates/landing/src/app/page.tsx +13 -0
- package/dist/cli/templates/landing/src/components/CTA.tsx +23 -0
- package/dist/cli/templates/landing/src/components/Features.tsx +46 -0
- package/dist/cli/templates/landing/src/components/Hero.tsx +26 -0
- package/dist/cli/templates/portfolio/AGENT.md +24 -0
- package/dist/cli/templates/portfolio/src/app/page.tsx +50 -0
- package/dist/cli/templates/portfolio/src/components/ProjectCard.tsx +30 -0
- package/dist/cli/templates/saas/AGENT.md +28 -0
- package/dist/cli/templates/saas/src/app/dashboard/page.tsx +10 -0
- package/dist/cli/templates/saas/src/app/page.tsx +37 -0
- package/dist/cli/templates/saas/src/app/pricing/page.tsx +53 -0
- package/dist/cli/templates/saas/src/components/Navbar.tsx +25 -0
- package/dist/cli/templates/saas/src/components/PricingCard.tsx +46 -0
- package/dist/cli/templates/templates/blank/AGENT.md +24 -0
- package/dist/cli/templates/templates/blank/src/app/page.tsx +10 -0
- package/dist/cli/templates/templates/blog/AGENT.md +26 -0
- package/dist/cli/templates/templates/blog/src/app/blog/[slug]/page.tsx +38 -0
- package/dist/cli/templates/templates/blog/src/app/page.tsx +35 -0
- package/dist/cli/templates/templates/blog/src/lib/posts.ts +42 -0
- package/dist/cli/templates/templates/dashboard/AGENT.md +26 -0
- package/dist/cli/templates/templates/dashboard/src/app/layout.tsx +28 -0
- package/dist/cli/templates/templates/dashboard/src/app/page.tsx +30 -0
- package/dist/cli/templates/templates/dashboard/src/components/Sidebar.tsx +31 -0
- package/dist/cli/templates/templates/dashboard/src/components/StatsCard.tsx +24 -0
- package/dist/cli/templates/templates/landing/AGENT.md +26 -0
- package/dist/cli/templates/templates/landing/src/app/page.tsx +13 -0
- package/dist/cli/templates/templates/landing/src/components/CTA.tsx +23 -0
- package/dist/cli/templates/templates/landing/src/components/Features.tsx +46 -0
- package/dist/cli/templates/templates/landing/src/components/Hero.tsx +26 -0
- package/dist/cli/templates/templates/portfolio/AGENT.md +24 -0
- package/dist/cli/templates/templates/portfolio/src/app/page.tsx +50 -0
- package/dist/cli/templates/templates/portfolio/src/components/ProjectCard.tsx +30 -0
- package/dist/cli/templates/templates/saas/AGENT.md +28 -0
- package/dist/cli/templates/templates/saas/src/app/dashboard/page.tsx +10 -0
- package/dist/cli/templates/templates/saas/src/app/page.tsx +37 -0
- package/dist/cli/templates/templates/saas/src/app/pricing/page.tsx +53 -0
- package/dist/cli/templates/templates/saas/src/components/Navbar.tsx +25 -0
- package/dist/cli/templates/templates/saas/src/components/PricingCard.tsx +46 -0
- package/dist/dashboard/assets/index-3djfaQxV.js +323 -0
- package/dist/dashboard/assets/index-BQNq3kAP.css +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/host/host.js +2 -8
- package/package.json +2 -1
- package/dist/dashboard/assets/index-B374_cjZ.css +0 -1
- package/dist/dashboard/assets/index-BJ6wUfxa.js +0 -318
package/dist/cli/server.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ interface ServerOptions {
|
|
|
2
2
|
awelPort: number;
|
|
3
3
|
targetPort: number;
|
|
4
4
|
projectCwd: string;
|
|
5
|
+
fresh?: boolean;
|
|
5
6
|
}
|
|
6
|
-
export declare function startServer({ awelPort, targetPort, projectCwd }: ServerOptions): Promise<void>;
|
|
7
|
+
export declare function startServer({ awelPort, targetPort, projectCwd, fresh }: ServerOptions): Promise<void>;
|
|
7
8
|
export {};
|
package/dist/cli/server.js
CHANGED
|
@@ -8,6 +8,7 @@ import { createInspectorRoute } from './inspector.js';
|
|
|
8
8
|
import { createCommentPopupRoute } from './comment-popup.js';
|
|
9
9
|
import { trackProxySocket } from './devserver.js';
|
|
10
10
|
import { getMimeType } from './config.js';
|
|
11
|
+
import { markProjectReady } from './awel-config.js';
|
|
11
12
|
import { awel } from './logger.js';
|
|
12
13
|
import { fileURLToPath } from 'url';
|
|
13
14
|
import { dirname, join } from 'path';
|
|
@@ -37,8 +38,9 @@ function serveDashboardIndex() {
|
|
|
37
38
|
return null;
|
|
38
39
|
return readFileSync(indexPath, 'utf-8');
|
|
39
40
|
}
|
|
40
|
-
export async function startServer({ awelPort, targetPort, projectCwd }) {
|
|
41
|
+
export async function startServer({ awelPort, targetPort, projectCwd, fresh }) {
|
|
41
42
|
const app = new Hono();
|
|
43
|
+
let isFresh = fresh ?? false;
|
|
42
44
|
// Create a proxy for WebSocket connections
|
|
43
45
|
const wsProxy = httpProxy.createProxyServer({
|
|
44
46
|
target: `http://localhost:${targetPort}`,
|
|
@@ -52,13 +54,22 @@ export async function startServer({ awelPort, targetPort, projectCwd }) {
|
|
|
52
54
|
trackProxySocket(proxySocket);
|
|
53
55
|
});
|
|
54
56
|
// Mount agent API routes
|
|
55
|
-
app.route('/', createAgentRoute(projectCwd, targetPort));
|
|
57
|
+
app.route('/', createAgentRoute(projectCwd, targetPort, () => isFresh));
|
|
56
58
|
// Mount undo API routes
|
|
57
59
|
app.route('/', createUndoRoute(projectCwd));
|
|
58
60
|
// Mount inspector relay routes
|
|
59
61
|
app.route('/', createInspectorRoute(projectCwd));
|
|
60
62
|
// Serve the comment popup page (loaded in an iframe by the host script)
|
|
61
63
|
app.route('/', createCommentPopupRoute());
|
|
64
|
+
// ─── Project Status Endpoints ─────────────────────────────
|
|
65
|
+
app.get('/api/project/status', (c) => {
|
|
66
|
+
return c.json({ fresh: isFresh });
|
|
67
|
+
});
|
|
68
|
+
app.post('/api/project/mark-ready', (c) => {
|
|
69
|
+
markProjectReady(projectCwd);
|
|
70
|
+
isFresh = false;
|
|
71
|
+
return c.json({ success: true });
|
|
72
|
+
});
|
|
62
73
|
// Serve the host script
|
|
63
74
|
app.get('/_awel/host.js', async (c) => {
|
|
64
75
|
const hostDistPath = join(__dirname, '../host/host.js');
|
|
@@ -89,7 +100,7 @@ export async function startServer({ awelPort, targetPort, projectCwd }) {
|
|
|
89
100
|
return c.text('Not found', 404);
|
|
90
101
|
});
|
|
91
102
|
// Proxy all other requests to the target app
|
|
92
|
-
app.all('*', createProxyMiddleware(targetPort, projectCwd));
|
|
103
|
+
app.all('*', createProxyMiddleware(targetPort, projectCwd, () => isFresh));
|
|
93
104
|
// Create the HTTP server with Hono
|
|
94
105
|
const server = serve({
|
|
95
106
|
fetch: app.fetch,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Project Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This is a blank Next.js project created with Awel. It uses the App Router, TypeScript, and Tailwind CSS.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
- `src/app/page.tsx` — Home page
|
|
10
|
+
- `src/app/layout.tsx` — Root layout with metadata and fonts
|
|
11
|
+
- `src/app/globals.css` — Global styles and Tailwind imports
|
|
12
|
+
|
|
13
|
+
## Conventions
|
|
14
|
+
|
|
15
|
+
- Use server components by default; add `'use client'` only when needed
|
|
16
|
+
- Style with Tailwind CSS utility classes
|
|
17
|
+
- Keep components in `src/components/`
|
|
18
|
+
- Use TypeScript for all files
|
|
19
|
+
|
|
20
|
+
## Example Prompts
|
|
21
|
+
|
|
22
|
+
- "Add a navigation bar with links to Home and About pages"
|
|
23
|
+
- "Create an About page at /about with a brief bio section"
|
|
24
|
+
- "Add a dark mode toggle using Tailwind's dark: variant"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default function Home() {
|
|
2
|
+
return (
|
|
3
|
+
<main className="flex min-h-screen flex-col items-center justify-center p-8">
|
|
4
|
+
<h1 className="text-4xl font-bold tracking-tight">Welcome to your new project</h1>
|
|
5
|
+
<p className="mt-4 text-lg text-gray-600 dark:text-gray-400">
|
|
6
|
+
Open the Awel overlay to start building with AI.
|
|
7
|
+
</p>
|
|
8
|
+
</main>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Project Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A blog application built with Next.js, TypeScript, and Tailwind CSS. Features a post listing page and dynamic post pages.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
- `src/app/page.tsx` — Blog listing page showing all posts
|
|
10
|
+
- `src/app/blog/[slug]/page.tsx` — Dynamic blog post page
|
|
11
|
+
- `src/lib/posts.ts` — Post data and utility functions
|
|
12
|
+
|
|
13
|
+
## Conventions
|
|
14
|
+
|
|
15
|
+
- Use server components by default; add `'use client'` only when needed
|
|
16
|
+
- Style with Tailwind CSS utility classes
|
|
17
|
+
- Keep components in `src/components/`
|
|
18
|
+
- Use TypeScript for all files
|
|
19
|
+
- Posts are stored as data in `src/lib/posts.ts` (replace with a CMS or MDX later)
|
|
20
|
+
|
|
21
|
+
## Example Prompts
|
|
22
|
+
|
|
23
|
+
- "Add a new blog post about getting started with Next.js"
|
|
24
|
+
- "Add tags to posts and create a filter by tag"
|
|
25
|
+
- "Add a search bar to filter posts by title"
|
|
26
|
+
- "Create an RSS feed at /feed.xml"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Link from 'next/link';
|
|
2
|
+
import { notFound } from 'next/navigation';
|
|
3
|
+
import { getPostBySlug, getAllPosts } from '@/lib/posts';
|
|
4
|
+
|
|
5
|
+
export function generateStaticParams() {
|
|
6
|
+
return getAllPosts().map((post) => ({ slug: post.slug }));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
|
|
10
|
+
const { slug } = await params;
|
|
11
|
+
const post = getPostBySlug(slug);
|
|
12
|
+
|
|
13
|
+
if (!post) {
|
|
14
|
+
notFound();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<main className="mx-auto max-w-3xl px-6 py-16">
|
|
19
|
+
<Link
|
|
20
|
+
href="/"
|
|
21
|
+
className="text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
|
|
22
|
+
>
|
|
23
|
+
← Back to blog
|
|
24
|
+
</Link>
|
|
25
|
+
<article className="mt-8">
|
|
26
|
+
<time className="text-sm text-gray-500 dark:text-gray-400">
|
|
27
|
+
{post.date}
|
|
28
|
+
</time>
|
|
29
|
+
<h1 className="mt-2 text-4xl font-bold tracking-tight">
|
|
30
|
+
{post.title}
|
|
31
|
+
</h1>
|
|
32
|
+
<div className="prose prose-gray mt-8 dark:prose-invert">
|
|
33
|
+
<p>{post.content}</p>
|
|
34
|
+
</div>
|
|
35
|
+
</article>
|
|
36
|
+
</main>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Link from 'next/link';
|
|
2
|
+
import { getAllPosts } from '@/lib/posts';
|
|
3
|
+
|
|
4
|
+
export default function BlogHome() {
|
|
5
|
+
const posts = getAllPosts();
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<main className="mx-auto max-w-3xl px-6 py-16">
|
|
9
|
+
<h1 className="text-4xl font-bold tracking-tight">Blog</h1>
|
|
10
|
+
<p className="mt-4 text-gray-600 dark:text-gray-400">
|
|
11
|
+
Thoughts, ideas, and tutorials.
|
|
12
|
+
</p>
|
|
13
|
+
<div className="mt-12 space-y-10">
|
|
14
|
+
{posts.map((post) => (
|
|
15
|
+
<article key={post.slug}>
|
|
16
|
+
<time className="text-sm text-gray-500 dark:text-gray-400">
|
|
17
|
+
{post.date}
|
|
18
|
+
</time>
|
|
19
|
+
<h2 className="mt-1 text-xl font-semibold">
|
|
20
|
+
<Link
|
|
21
|
+
href={`/blog/${post.slug}`}
|
|
22
|
+
className="hover:underline"
|
|
23
|
+
>
|
|
24
|
+
{post.title}
|
|
25
|
+
</Link>
|
|
26
|
+
</h2>
|
|
27
|
+
<p className="mt-2 text-gray-600 dark:text-gray-400">
|
|
28
|
+
{post.excerpt}
|
|
29
|
+
</p>
|
|
30
|
+
</article>
|
|
31
|
+
))}
|
|
32
|
+
</div>
|
|
33
|
+
</main>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface Post {
|
|
2
|
+
slug: string;
|
|
3
|
+
title: string;
|
|
4
|
+
date: string;
|
|
5
|
+
excerpt: string;
|
|
6
|
+
content: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const posts: Post[] = [
|
|
10
|
+
{
|
|
11
|
+
slug: 'getting-started',
|
|
12
|
+
title: 'Getting Started with Awel',
|
|
13
|
+
date: '2025-01-15',
|
|
14
|
+
excerpt: 'Learn how to set up your first project with Awel and Next.js.',
|
|
15
|
+
content:
|
|
16
|
+
'Awel is an AI-powered development overlay for Next.js. It helps you build, modify, and understand your code with an interactive AI assistant. To get started, run npx awel dev in your project directory and look for the floating button in the bottom-right corner.',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
slug: 'building-with-ai',
|
|
20
|
+
title: 'Building with AI Assistance',
|
|
21
|
+
date: '2025-01-10',
|
|
22
|
+
excerpt: 'How AI-assisted development can speed up your workflow.',
|
|
23
|
+
content:
|
|
24
|
+
'AI-assisted development is transforming how we build software. With tools like Awel, you can describe what you want to build in natural language, and the AI will help you write the code. This approach is especially powerful for scaffolding new features, debugging issues, and learning new frameworks.',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
slug: 'nextjs-best-practices',
|
|
28
|
+
title: 'Next.js Best Practices',
|
|
29
|
+
date: '2025-01-05',
|
|
30
|
+
excerpt: 'Tips and patterns for building performant Next.js applications.',
|
|
31
|
+
content:
|
|
32
|
+
'Next.js provides many built-in optimizations, but there are additional patterns you can follow. Use server components by default and only add the use client directive when you need interactivity. Leverage the Image component for automatic optimization. Use dynamic imports for heavy components that are not needed on initial load.',
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export function getAllPosts(): Post[] {
|
|
37
|
+
return posts.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getPostBySlug(slug: string): Post | undefined {
|
|
41
|
+
return posts.find((post) => post.slug === slug);
|
|
42
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Project Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A dashboard application built with Next.js, TypeScript, and Tailwind CSS. Features a sidebar navigation and stats cards.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
- `src/app/page.tsx` — Dashboard main page with stats overview
|
|
10
|
+
- `src/app/layout.tsx` — Root layout with sidebar
|
|
11
|
+
- `src/components/Sidebar.tsx` — Sidebar navigation component
|
|
12
|
+
- `src/components/StatsCard.tsx` — Reusable stats card component
|
|
13
|
+
|
|
14
|
+
## Conventions
|
|
15
|
+
|
|
16
|
+
- Use server components by default; add `'use client'` only when needed
|
|
17
|
+
- Style with Tailwind CSS utility classes
|
|
18
|
+
- Keep components in `src/components/`
|
|
19
|
+
- Use TypeScript for all files
|
|
20
|
+
|
|
21
|
+
## Example Prompts
|
|
22
|
+
|
|
23
|
+
- "Add a new page for user settings at /settings"
|
|
24
|
+
- "Add a chart component to the dashboard showing weekly data"
|
|
25
|
+
- "Create a data table component with sorting"
|
|
26
|
+
- "Add a notification bell icon to the sidebar header"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Metadata } from 'next';
|
|
2
|
+
import { Inter } from 'next/font/google';
|
|
3
|
+
import './globals.css';
|
|
4
|
+
import { Sidebar } from '@/components/Sidebar';
|
|
5
|
+
|
|
6
|
+
const inter = Inter({ subsets: ['latin'] });
|
|
7
|
+
|
|
8
|
+
export const metadata: Metadata = {
|
|
9
|
+
title: 'Dashboard',
|
|
10
|
+
description: 'Dashboard application built with Awel',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default function RootLayout({
|
|
14
|
+
children,
|
|
15
|
+
}: {
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
}) {
|
|
18
|
+
return (
|
|
19
|
+
<html lang="en">
|
|
20
|
+
<body className={inter.className}>
|
|
21
|
+
<div className="flex min-h-screen">
|
|
22
|
+
<Sidebar />
|
|
23
|
+
<main className="flex-1 p-8">{children}</main>
|
|
24
|
+
</div>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { StatsCard } from '@/components/StatsCard';
|
|
2
|
+
|
|
3
|
+
const stats = [
|
|
4
|
+
{ title: 'Total Users', value: '2,847', change: '+12.5%', trend: 'up' as const },
|
|
5
|
+
{ title: 'Revenue', value: '$45,231', change: '+8.2%', trend: 'up' as const },
|
|
6
|
+
{ title: 'Active Sessions', value: '1,024', change: '-3.1%', trend: 'down' as const },
|
|
7
|
+
{ title: 'Conversion Rate', value: '3.24%', change: '+1.8%', trend: 'up' as const },
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
export default function Dashboard() {
|
|
11
|
+
return (
|
|
12
|
+
<div>
|
|
13
|
+
<h1 className="text-2xl font-bold">Dashboard</h1>
|
|
14
|
+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
|
15
|
+
Welcome back. Here's an overview of your metrics.
|
|
16
|
+
</p>
|
|
17
|
+
<div className="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
|
18
|
+
{stats.map((stat) => (
|
|
19
|
+
<StatsCard key={stat.title} {...stat} />
|
|
20
|
+
))}
|
|
21
|
+
</div>
|
|
22
|
+
<div className="mt-8 rounded-xl border border-gray-200 p-6 dark:border-gray-800">
|
|
23
|
+
<h2 className="text-lg font-semibold">Recent Activity</h2>
|
|
24
|
+
<p className="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
|
25
|
+
No recent activity to display. Ask Awel to add a data table or chart here.
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const navItems = [
|
|
2
|
+
{ label: 'Dashboard', href: '/', icon: '📊' },
|
|
3
|
+
{ label: 'Analytics', href: '/analytics', icon: '📈' },
|
|
4
|
+
{ label: 'Users', href: '/users', icon: '👥' },
|
|
5
|
+
{ label: 'Settings', href: '/settings', icon: '⚙️' },
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
export function Sidebar() {
|
|
9
|
+
return (
|
|
10
|
+
<aside className="flex w-64 flex-col border-r border-gray-200 bg-gray-50 dark:border-gray-800 dark:bg-gray-900">
|
|
11
|
+
<div className="flex h-16 items-center px-6">
|
|
12
|
+
<span className="text-lg font-bold">MyApp</span>
|
|
13
|
+
</div>
|
|
14
|
+
<nav className="flex-1 px-4 py-4">
|
|
15
|
+
<ul className="space-y-1">
|
|
16
|
+
{navItems.map((item) => (
|
|
17
|
+
<li key={item.href}>
|
|
18
|
+
<a
|
|
19
|
+
href={item.href}
|
|
20
|
+
className="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-200 dark:text-gray-300 dark:hover:bg-gray-800"
|
|
21
|
+
>
|
|
22
|
+
<span>{item.icon}</span>
|
|
23
|
+
{item.label}
|
|
24
|
+
</a>
|
|
25
|
+
</li>
|
|
26
|
+
))}
|
|
27
|
+
</ul>
|
|
28
|
+
</nav>
|
|
29
|
+
</aside>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface StatsCardProps {
|
|
2
|
+
title: string;
|
|
3
|
+
value: string;
|
|
4
|
+
change: string;
|
|
5
|
+
trend: 'up' | 'down';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function StatsCard({ title, value, change, trend }: StatsCardProps) {
|
|
9
|
+
return (
|
|
10
|
+
<div className="rounded-xl border border-gray-200 p-6 dark:border-gray-800">
|
|
11
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">{title}</p>
|
|
12
|
+
<p className="mt-2 text-3xl font-bold">{value}</p>
|
|
13
|
+
<p
|
|
14
|
+
className={`mt-2 text-sm font-medium ${
|
|
15
|
+
trend === 'up'
|
|
16
|
+
? 'text-green-600 dark:text-green-400'
|
|
17
|
+
: 'text-red-600 dark:text-red-400'
|
|
18
|
+
}`}
|
|
19
|
+
>
|
|
20
|
+
{change}
|
|
21
|
+
</p>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Project Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A landing page built with Next.js, TypeScript, and Tailwind CSS. Features a hero section, features grid, and call-to-action.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
- `src/app/page.tsx` — Main landing page (composes Hero, Features, CTA)
|
|
10
|
+
- `src/components/Hero.tsx` — Hero section with headline and CTA button
|
|
11
|
+
- `src/components/Features.tsx` — Features grid (3 columns)
|
|
12
|
+
- `src/components/CTA.tsx` — Call-to-action section and footer
|
|
13
|
+
|
|
14
|
+
## Conventions
|
|
15
|
+
|
|
16
|
+
- Use server components by default; add `'use client'` only when needed
|
|
17
|
+
- Style with Tailwind CSS utility classes
|
|
18
|
+
- Keep components in `src/components/`
|
|
19
|
+
- Use TypeScript for all files
|
|
20
|
+
|
|
21
|
+
## Example Prompts
|
|
22
|
+
|
|
23
|
+
- "Change the hero headline and add a subtitle"
|
|
24
|
+
- "Add a fourth feature card about security"
|
|
25
|
+
- "Add a testimonials section between Features and CTA"
|
|
26
|
+
- "Make the CTA section have a gradient background"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function CTA() {
|
|
2
|
+
return (
|
|
3
|
+
<section id="cta" className="px-6 py-24">
|
|
4
|
+
<div className="mx-auto max-w-3xl rounded-2xl bg-gray-900 px-8 py-16 text-center dark:bg-gray-800">
|
|
5
|
+
<h2 className="text-3xl font-bold tracking-tight text-white">
|
|
6
|
+
Ready to get started?
|
|
7
|
+
</h2>
|
|
8
|
+
<p className="mt-4 text-gray-300">
|
|
9
|
+
Start building your project with AI-assisted development.
|
|
10
|
+
</p>
|
|
11
|
+
<a
|
|
12
|
+
href="#"
|
|
13
|
+
className="mt-8 inline-block rounded-lg bg-white px-6 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100"
|
|
14
|
+
>
|
|
15
|
+
Start building
|
|
16
|
+
</a>
|
|
17
|
+
</div>
|
|
18
|
+
<footer className="mt-16 text-center text-sm text-gray-500">
|
|
19
|
+
Built with Awel and Next.js
|
|
20
|
+
</footer>
|
|
21
|
+
</section>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const features = [
|
|
2
|
+
{
|
|
3
|
+
title: 'Lightning Fast',
|
|
4
|
+
description: 'Built on Next.js with optimized rendering and automatic code splitting for peak performance.',
|
|
5
|
+
icon: '⚡',
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
title: 'AI-Powered',
|
|
9
|
+
description: 'Develop faster with Awel — your AI coding assistant that understands your entire project.',
|
|
10
|
+
icon: '🤖',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
title: 'Beautiful Design',
|
|
14
|
+
description: 'Tailwind CSS utility-first styling makes it easy to create responsive, polished interfaces.',
|
|
15
|
+
icon: '🎨',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export function Features() {
|
|
20
|
+
return (
|
|
21
|
+
<section id="features" className="px-6 py-24">
|
|
22
|
+
<div className="mx-auto max-w-5xl">
|
|
23
|
+
<h2 className="text-center text-3xl font-bold tracking-tight">
|
|
24
|
+
Everything you need
|
|
25
|
+
</h2>
|
|
26
|
+
<p className="mt-4 text-center text-gray-600 dark:text-gray-400">
|
|
27
|
+
Start with a solid foundation and build from there.
|
|
28
|
+
</p>
|
|
29
|
+
<div className="mt-16 grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
|
30
|
+
{features.map((feature) => (
|
|
31
|
+
<div
|
|
32
|
+
key={feature.title}
|
|
33
|
+
className="rounded-xl border border-gray-200 p-6 dark:border-gray-800"
|
|
34
|
+
>
|
|
35
|
+
<div className="text-3xl">{feature.icon}</div>
|
|
36
|
+
<h3 className="mt-4 text-lg font-semibold">{feature.title}</h3>
|
|
37
|
+
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
|
38
|
+
{feature.description}
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
))}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</section>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function Hero() {
|
|
2
|
+
return (
|
|
3
|
+
<section className="flex flex-col items-center justify-center px-6 py-24 text-center">
|
|
4
|
+
<h1 className="max-w-3xl text-5xl font-bold tracking-tight sm:text-6xl">
|
|
5
|
+
Build something amazing
|
|
6
|
+
</h1>
|
|
7
|
+
<p className="mt-6 max-w-xl text-lg text-gray-600 dark:text-gray-400">
|
|
8
|
+
A modern landing page template powered by Next.js, Tailwind CSS, and AI-assisted development with Awel.
|
|
9
|
+
</p>
|
|
10
|
+
<div className="mt-10 flex gap-4">
|
|
11
|
+
<a
|
|
12
|
+
href="#features"
|
|
13
|
+
className="rounded-lg bg-gray-900 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:bg-gray-800 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-100"
|
|
14
|
+
>
|
|
15
|
+
Get started
|
|
16
|
+
</a>
|
|
17
|
+
<a
|
|
18
|
+
href="#cta"
|
|
19
|
+
className="rounded-lg border border-gray-300 px-6 py-3 text-sm font-semibold text-gray-900 hover:bg-gray-50 dark:border-gray-700 dark:text-white dark:hover:bg-gray-800"
|
|
20
|
+
>
|
|
21
|
+
Learn more
|
|
22
|
+
</a>
|
|
23
|
+
</div>
|
|
24
|
+
</section>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Project Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A portfolio website built with Next.js, TypeScript, and Tailwind CSS. Showcases projects with a card-based layout.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
- `src/app/page.tsx` — Portfolio main page with intro and project grid
|
|
10
|
+
- `src/components/ProjectCard.tsx` — Reusable project card component
|
|
11
|
+
|
|
12
|
+
## Conventions
|
|
13
|
+
|
|
14
|
+
- Use server components by default; add `'use client'` only when needed
|
|
15
|
+
- Style with Tailwind CSS utility classes
|
|
16
|
+
- Keep components in `src/components/`
|
|
17
|
+
- Use TypeScript for all files
|
|
18
|
+
|
|
19
|
+
## Example Prompts
|
|
20
|
+
|
|
21
|
+
- "Add a contact form section at the bottom of the page"
|
|
22
|
+
- "Add a skills section showing technologies I know"
|
|
23
|
+
- "Create a project detail page at /projects/[slug]"
|
|
24
|
+
- "Add animation to the project cards on hover"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ProjectCard } from '@/components/ProjectCard';
|
|
2
|
+
|
|
3
|
+
const projects = [
|
|
4
|
+
{
|
|
5
|
+
title: 'Project Alpha',
|
|
6
|
+
description: 'A full-stack web application built with Next.js and PostgreSQL.',
|
|
7
|
+
tags: ['Next.js', 'TypeScript', 'PostgreSQL'],
|
|
8
|
+
href: '#',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
title: 'Project Beta',
|
|
12
|
+
description: 'A mobile-first e-commerce platform with real-time inventory.',
|
|
13
|
+
tags: ['React Native', 'Node.js', 'Redis'],
|
|
14
|
+
href: '#',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
title: 'Project Gamma',
|
|
18
|
+
description: 'An open-source CLI tool for automating deployment workflows.',
|
|
19
|
+
tags: ['Go', 'Docker', 'CI/CD'],
|
|
20
|
+
href: '#',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
title: 'Project Delta',
|
|
24
|
+
description: 'A real-time collaborative document editor with conflict resolution.',
|
|
25
|
+
tags: ['WebSocket', 'CRDT', 'React'],
|
|
26
|
+
href: '#',
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
export default function Portfolio() {
|
|
31
|
+
return (
|
|
32
|
+
<main className="mx-auto max-w-4xl px-6 py-16">
|
|
33
|
+
<section className="mb-16">
|
|
34
|
+
<h1 className="text-4xl font-bold tracking-tight">Hi, I'm a developer</h1>
|
|
35
|
+
<p className="mt-4 max-w-2xl text-lg text-gray-600 dark:text-gray-400">
|
|
36
|
+
I build web applications and open-source tools. This portfolio was
|
|
37
|
+
scaffolded with Awel — ask the AI to customize it for you.
|
|
38
|
+
</p>
|
|
39
|
+
</section>
|
|
40
|
+
<section>
|
|
41
|
+
<h2 className="text-2xl font-bold">Projects</h2>
|
|
42
|
+
<div className="mt-8 grid gap-6 sm:grid-cols-2">
|
|
43
|
+
{projects.map((project) => (
|
|
44
|
+
<ProjectCard key={project.title} {...project} />
|
|
45
|
+
))}
|
|
46
|
+
</div>
|
|
47
|
+
</section>
|
|
48
|
+
</main>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
interface ProjectCardProps {
|
|
2
|
+
title: string;
|
|
3
|
+
description: string;
|
|
4
|
+
tags: string[];
|
|
5
|
+
href: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function ProjectCard({ title, description, tags, href }: ProjectCardProps) {
|
|
9
|
+
return (
|
|
10
|
+
<a
|
|
11
|
+
href={href}
|
|
12
|
+
className="group block rounded-xl border border-gray-200 p-6 transition-colors hover:border-gray-400 dark:border-gray-800 dark:hover:border-gray-600"
|
|
13
|
+
>
|
|
14
|
+
<h3 className="text-lg font-semibold group-hover:underline">{title}</h3>
|
|
15
|
+
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
|
|
16
|
+
{description}
|
|
17
|
+
</p>
|
|
18
|
+
<div className="mt-4 flex flex-wrap gap-2">
|
|
19
|
+
{tags.map((tag) => (
|
|
20
|
+
<span
|
|
21
|
+
key={tag}
|
|
22
|
+
className="rounded-full bg-gray-100 px-3 py-1 text-xs font-medium text-gray-700 dark:bg-gray-800 dark:text-gray-300"
|
|
23
|
+
>
|
|
24
|
+
{tag}
|
|
25
|
+
</span>
|
|
26
|
+
))}
|
|
27
|
+
</div>
|
|
28
|
+
</a>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Project Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A SaaS application template built with Next.js, TypeScript, and Tailwind CSS. Includes a marketing landing page, pricing page, and dashboard shell.
|
|
6
|
+
|
|
7
|
+
## Structure
|
|
8
|
+
|
|
9
|
+
- `src/app/page.tsx` — SaaS marketing landing page
|
|
10
|
+
- `src/app/pricing/page.tsx` — Pricing page with plan comparison
|
|
11
|
+
- `src/app/dashboard/page.tsx` — Authenticated dashboard shell
|
|
12
|
+
- `src/components/Navbar.tsx` — Top navigation bar
|
|
13
|
+
- `src/components/PricingCard.tsx` — Reusable pricing card component
|
|
14
|
+
|
|
15
|
+
## Conventions
|
|
16
|
+
|
|
17
|
+
- Use server components by default; add `'use client'` only when needed
|
|
18
|
+
- Style with Tailwind CSS utility classes
|
|
19
|
+
- Keep components in `src/components/`
|
|
20
|
+
- Use TypeScript for all files
|
|
21
|
+
- The Navbar is shared across marketing pages
|
|
22
|
+
|
|
23
|
+
## Example Prompts
|
|
24
|
+
|
|
25
|
+
- "Add a features comparison table to the pricing page"
|
|
26
|
+
- "Create a sign-up form with email and password fields"
|
|
27
|
+
- "Add a testimonials carousel to the landing page"
|
|
28
|
+
- "Build a billing settings page at /dashboard/billing"
|