Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,20 @@ OPENAI_API_KEY=your_openai_api_key_here
GEMINI_API_KEY=your_gemini_api_key_here

# Get yours at https://console.groq.com
GROQ_API_KEY=your_groq_api_key_here
GROQ_API_KEY=your_groq_api_key_here

# REQUIRED - Supabase credentials
# Get yours at https://supabase.com/dashboard
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url_here
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key_here
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key_here
DATABASE_URL=your_supabase_database_url_here

# REQUIRED - Payment provider credentials
PAYSTACK_SECRET_KEY=your_paystack_secret_key_here
FLUTTERWAVE_PUBLIC_KEY=your_flutterwave_public_key_here
FLUTTERWAVE_SECRET_KEY=your_flutterwave_secret_key_here
FLUTTERWAVE_SECRET_HASH=your_flutterwave_secret_hash_here

# REQUIRED - App URL for redirects
NEXT_PUBLIC_APP_URL=http://localhost:3000
36 changes: 36 additions & 0 deletions .env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# REQUIRED - Sandboxes for code execution
# Get yours at https://e2b.dev
E2B_API_KEY=your_e2b_api_key_here

# REQUIRED - Web scraping for cloning websites
# Get yours at https://firecrawl.dev
FIRECRAWL_API_KEY=your_firecrawl_api_key_here

# OPTIONAL - AI Providers (need at least one)
# Get yours at https://console.anthropic.com
ANTHROPIC_API_KEY=your_anthropic_api_key_here

# Get yours at https://platform.openai.com
OPENAI_API_KEY=your_openai_api_key_here

# Get yours at https://aistudio.google.com/app/apikey
GEMINI_API_KEY=your_gemini_api_key_here

# Get yours at https://console.groq.com
GROQ_API_KEY=your_groq_api_key_here

# REQUIRED - Supabase credentials
# Get yours at https://supabase.com/dashboard
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url_here
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key_here
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key_here
DATABASE_URL=your_supabase_database_url_here

# REQUIRED - Payment provider credentials
PAYSTACK_SECRET_KEY=your_paystack_secret_key_here
FLUTTERWAVE_PUBLIC_KEY=your_flutterwave_public_key_here
FLUTTERWAVE_SECRET_KEY=your_flutterwave_secret_key_here
FLUTTERWAVE_SECRET_HASH=your_flutterwave_secret_hash_here

# REQUIRED - App URL for redirects
NEXT_PUBLIC_APP_URL=http://localhost:3000
73 changes: 68 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
# Open Lovable
# Sokarr.ai

Chat with AI to build React apps instantly. An example app made by the [Firecrawl](https://firecrawl.dev/?ref=open-lovable-github) team. For a complete cloud solution, check out [Lovable.dev ❤️](https://lovable.dev/).
Chat with AI to build React apps instantly.

<img src="https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExbmZtaHFleGRsMTNlaWNydGdianI4NGQ4dHhyZjB0d2VkcjRyeXBucCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ZFVLWMa6dVskQX0qu1/giphy.gif" alt="Open Lovable Demo" width="100%"/>
<img src="https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExbmZtaHFleGRsMTNlaWNydGdianI4NGQ4dHhyZjB0d2VkcjRyeXBucCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/ZFVLWMa6dVskQX0qu1/giphy.gif" alt="Sokarr.ai Demo" width="100%"/>

## Features

* **AI-Powered App Generation:** Build React applications by chatting with an AI.
* **Subscription System:** Monetize your application with a subscription system powered by Paystack and Flutterwave.
* **Persistent AI Memory:** The AI remembers your conversation history across sessions.
* **GitHub Integration:** Import your existing GitHub repositories or export your work to a new repository.
* **Multi-Language Support:** The sandbox environment supports multiple languages, including PHP, Node.js, and more.
* **Website Cloning:** Re-imagine any website in seconds by providing a URL.

## Setup

Expand All @@ -15,7 +22,20 @@ cd open-lovable
npm install
```

2. **Add `.env.local`**
2. **Set up Supabase**
- Go to [Supabase](https://supabase.com/) and create a new project.
- Go to the "Authentication" section and enable the Google and GitHub providers. You will need to get the client ID and secret for each provider from their respective developer consoles.
- In the GitHub provider settings, make sure to request the `repo` scope.
- Go to the "Database" section and get your database connection string.
- Go to the "Settings" > "API" section and get your Project URL, anon key, and service role key.

3. **Set up Payment Providers**
- Create accounts on [Paystack](https://paystack.com/) and [Flutterwave](https://flutterwave.com/).
- Get your API keys (public and secret) from your provider dashboards.
- For Flutterwave, you will also need to set up a webhook and get the secret hash.

4. **Add `.env.local`**
Create a `.env.local` file in the root of the project and add the following environment variables:
```env
# Required
E2B_API_KEY=your_e2b_api_key # Get from https://e2b.dev (Sandboxes)
Expand All @@ -26,15 +46,58 @@ ANTHROPIC_API_KEY=your_anthropic_api_key # Get from https://console.anthropic.c
OPENAI_API_KEY=your_openai_api_key # Get from https://platform.openai.com (GPT-5)
GEMINI_API_KEY=your_gemini_api_key # Get from https://aistudio.google.com/app/apikey
GROQ_API_KEY=your_groq_api_key # Get from https://console.groq.com (Fast inference - Kimi K2 recommended)

# Supabase credentials
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url_here
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key_here
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key_here
DATABASE_URL=your_supabase_database_url_here

# Payment provider credentials
PAYSTACK_SECRET_KEY=your_paystack_secret_key_here
FLUTTERWAVE_PUBLIC_KEY=your_flutterwave_public_key_here
FLUTTERWAVE_SECRET_KEY=your_flutterwave_secret_key_here
FLUTTERWAVE_SECRET_HASH=your_flutterwave_secret_hash_here

# App URL for redirects
NEXT_PUBLIC_APP_URL=http://localhost:3000
```

3. **Run**
5. **Run Database Migrations**
```bash
npm run db:generate
npm run db:migrate
```
This will create the necessary tables in your Supabase database.

6. **Run**
```bash
npm run dev
```

Open [http://localhost:3000](http://localhost:3000)

## How It Works

### Authentication
The application uses Supabase for authentication, supporting both Google and GitHub providers. When a user signs up, a corresponding entry is created in the `users` table in the database.

### Subscription System
The subscription system is built on top of Supabase and integrates with Paystack and Flutterwave.
- Users can choose from different subscription plans.
- When a user subscribes, a payment intent is created with the selected payment provider.
- After a successful payment, the provider sends a webhook to the application, which verifies the payment and updates the user's subscription status in the `subscriptions` table.

### AI and Sandbox
- The application uses E2B sandboxes to provide an isolated environment for running the AI-generated code.
- The AI's memory is persistent, thanks to the conversation history being stored in the Supabase database.
- The sandbox environment comes with support for multiple languages, including PHP and Node.js.

### GitHub Integration
- Users can connect their GitHub accounts to the application.
- They can import their existing repositories into a new sandbox to work on them with the AI.
- They can also export their work from the sandbox to a new GitHub repository.

## License

MIT
41 changes: 33 additions & 8 deletions app/api/create-ai-sandbox/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ declare global {
var sandboxState: SandboxState;
}

export async function POST() {
export async function POST(request: Request) {
const { files } = await request.json();
let sandbox: any = null;

try {
Expand Down Expand Up @@ -48,14 +49,37 @@ export async function POST() {
console.log(`[create-ai-sandbox] Sandbox created: ${sandboxId}`);
console.log(`[create-ai-sandbox] Sandbox host: ${host}`);

// Set up a basic Vite React app using Python to write files
console.log('[create-ai-sandbox] Setting up Vite React app...');

// Write all files in a single Python script to avoid multiple executions
const setupScript = `
if (files) {
// Write the imported files to the sandbox
const setupScript = `
import os
import json

print('Writing imported files to sandbox...')

${files.map((file: any) => `
os.makedirs(os.path.dirname('/home/user/app${file.path}'), exist_ok=True)
with open('/home/user/app${file.path}', 'w') as f:
f.write("""${file.content}""")
print('✓ ${file.path}')
`).join('\n')}

print('\\nAll files created successfully!')
`;
await sandbox.runCode(setupScript);
} else {
// Set up a basic Vite React app using Python to write files
console.log('[create-ai-sandbox] Setting up Vite React app...');

// Write all files in a single Python script to avoid multiple executions
const setupScript = `
import os
import json

print('Installing PHP...')
os.system('sudo apt-get update && sudo apt-get install -y php')
print('✓ PHP installed')

print('Setting up React app with Vite and Tailwind...')

# Create directory structure
Expand Down Expand Up @@ -225,8 +249,9 @@ print('✓ src/index.css')
print('\\nAll files created successfully!')
`;

// Execute the setup script
await sandbox.runCode(setupScript);
// Execute the setup script
await sandbox.runCode(setupScript);
}

// Install dependencies
console.log('[create-ai-sandbox] Installing dependencies...');
Expand Down
74 changes: 74 additions & 0 deletions app/api/create-payment-intent/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { NextResponse } from "next/server";
import { createClient } from "@/lib/supabase/server";
import { cookies } from "next/headers";
import paystack from "paystack";
import Flutterwave from "flutterwave-node-v3";

const paystackClient = paystack(process.env.PAYSTACK_SECRET_KEY!);
const flutterwaveClient = new Flutterwave(process.env.FLUTTERWAVE_PUBLIC_KEY!, process.env.FLUTTERWAVE_SECRET_KEY!);

const plans = {
"Pro": 1000, // in kobo for Paystack, assuming NGN for Flutterwave
"Pro+": 2500, // in kobo for Paystack, assuming NGN for Flutterwave
};

export async function POST(request: Request) {
const { plan, provider } = await request.json();
const cookieStore = cookies();
const supabase = createClient(cookieStore);

if (!plan || !provider) {
return NextResponse.json({ error: "Missing plan or provider" }, { status: 400 });
}

const { data: { user } } = await supabase.auth.getUser();

if (!user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}

const price = plans[plan as keyof typeof plans];
if (!price) {
return NextResponse.json({ error: "Invalid plan" }, { status: 400 });
}

if (provider === "paystack") {
const response = await paystackClient.transaction.initialize({
amount: price,
email: user.email!,
metadata: {
userId: user.id,
plan,
},
});

return NextResponse.json({ paymentUrl: response.data.authorization_url });
} else if (provider === "flutterwave") {
try {
const response = await flutterwaveClient.Payment.getLink({
tx_ref: `tx-${Date.now()}`,
amount: price / 100, // Flutterwave expects amount in major currency unit
currency: "NGN",
redirect_url: `${process.env.NEXT_PUBLIC_APP_URL}/payment-status`,
customer: {
email: user.email!,
name: user.email!,
},
customizations: {
title: "Sokarr.ai Subscription",
description: `Payment for ${plan} plan`,
},
meta: {
userId: user.id,
plan,
}
});
return NextResponse.json({ paymentUrl: response.data.link });
} catch (error) {
console.error(error);
return NextResponse.json({ error: "Failed to create Flutterwave payment link" }, { status: 500 });
}
} else {
return NextResponse.json({ error: "Invalid provider" }, { status: 400 });
}
}
Loading