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
86 changes: 86 additions & 0 deletions README.dev.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Local Development Setup

This document provides instructions for setting up and running the application in a local development environment. This setup uses a standard Node.js server and does not require any Cloudflare-specific services.

## Prerequisites

- Node.js (v18 or later)
- npm or bun

## Installation

1. **Install dependencies:**

```bash
npm install
```

or

```bash
bun install
```

2. **Set up the database:**

This project uses a local SQLite database. To set up the database and apply migrations, run the following command:

```bash
npx drizzle-kit push
```

## Authentication Setup (Clerk)

This project uses [Clerk](https://clerk.com/) for authentication. To get started, you will need to create a free Clerk account and set up a new application.

1. **Create a Clerk Application:**
- Go to the [Clerk Dashboard](https://dashboard.clerk.com/) and create a new application.
- Give your application a name and choose your preferred sign-in options.

2. **Get API Keys:**
- In your Clerk application dashboard, navigate to **API Keys**.
- You will need the **Publishable key** and the **Secret key**.

3. **Configure Environment Variables:**
- Create a new file named `.env` in the root of the project by copying the `.env.example` file.
- Open the `.env` file and add the keys you obtained from the Clerk dashboard:

```env
CLERK_SECRET_KEY="YOUR_CLERK_SECRET_KEY"
CLERK_PUBLISHABLE_KEY="YOUR_CLERK_PUBLISHABLE_KEY"
```

## Running the Application

1. **Start the backend server:**

To start the backend server, run the following command. This will start the Hono application on a Node.js server, which will be available at `http://localhost:3000` by default.

```bash
npm run dev:node
```

2. **Start the frontend development server:**

In a separate terminal, start the Vite frontend development server:

```bash
npm run dev
```

The frontend will be available at `http://localhost:5173`.

## Environment Variables

The application is configured using a `.env` file. See the `.env.example` file for a full list of available options.

```
# Clerk Authentication
CLERK_SECRET_KEY=
CLERK_PUBLISHABLE_KEY=

# Application
PORT=3000
CUSTOM_DOMAIN=localhost:5173
NODE_ENV=development
```
444 changes: 25 additions & 419 deletions bun.lock

Large diffs are not rendered by default.

26 changes: 0 additions & 26 deletions drizzle.config.local.ts

This file was deleted.

26 changes: 0 additions & 26 deletions drizzle.config.remote.ts

This file was deleted.

13 changes: 13 additions & 0 deletions drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineConfig } from 'drizzle-kit';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


export default defineConfig({
schema: './worker/database/schema.ts',
out: './migrations',
dialect: 'sqlite',
driver: 'better-sqlite',
dbCredentials: {
url: './data/sqlite.db',
},
verbose: true,
strict: true,
});
36 changes: 10 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,29 @@
"type": "module",
"scripts": {
"dev": "DEV_MODE=true vite",
"dev:worker": "DEV_MODE=true npm run build && wrangler dev --x-remote-bindings --port 5173",
"dev:remote": "DEV_MODE=true npm run build && wrangler dev --remote --port 5173",
"dev:node": "tsx watch worker/server.ts",
"build": "tsc -b --incremental && vite build",
"lint": "eslint .",
"preview": "npm run build && vite preview",
"deploy": "bun --env-file .prod.vars scripts/deploy.ts && bun run db:generate && bun run db:migrate:remote",
"local": "wrangler dev --experimental-vectorize-bind-to-prod --local",
"cf-typegen": "wrangler types --include-runtime false",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"db:generate": "drizzle-kit generate --config=drizzle.config.local.ts",
"db:generate:remote": "drizzle-kit generate --config=drizzle.config.remote.ts",
"db:migrate:local": "wrangler d1 migrations apply vibesdk-db --local",
"db:migrate:remote": "CI=true wrangler d1 migrations apply vibesdk-db --remote",
"db:push:local": "drizzle-kit push --config=drizzle.config.local.ts",
"db:push:remote": "drizzle-kit push --config=drizzle.config.remote.ts",
"db:studio": "drizzle-kit studio --config=drizzle.config.local.ts",
"db:studio:remote": "drizzle-kit studio --config=drizzle.config.remote.ts",
"db:generate": "drizzle-kit generate --config=drizzle.config.ts",
"db:push": "drizzle-kit push --config=drizzle.config.ts",
"db:studio": "drizzle-kit studio --config=drizzle.config.ts",
"db:setup": "bun run scripts/setup-database.ts",
"db:drop": "drizzle-kit drop --config=drizzle.config.local.ts",
"db:drop:remote": "drizzle-kit drop --config=drizzle.config.remote.ts",
"db:introspect": "drizzle-kit introspect --config=drizzle.config.local.ts",
"db:check": "drizzle-kit check --config=drizzle.config.local.ts",
"db:up": "drizzle-kit up --config=drizzle.config.local.ts",
"db:drop": "drizzle-kit drop --config=drizzle.config.ts",
"db:introspect": "drizzle-kit introspect --config=drizzle.config.ts",
"db:check": "drizzle-kit check --config=drizzle.config.ts",
"db:up": "drizzle-kit up --config=drizzle.config.ts",
"knip": "knip",
"knip:fix": "knip --fix",
"knip:production": "knip --production",
"knip:dependencies": "knip --dependencies",
"knip:exports": "knip --exports"
},
"dependencies": {
"@cloudflare/containers": "^0.0.25",
"@cloudflare/sandbox": "0.1.3",
"@hono/clerk-auth": "^3.0.3",
"@noble/ciphers": "^1.3.0",
"@octokit/rest": "^22.0.0",
"@radix-ui/react-accordion": "^1.2.12",
Expand Down Expand Up @@ -68,7 +57,6 @@
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"@rolldown/binding-linux-x64-gnu": "^1.0.0-beta.9-commit.d91dfb5",
"@sentry/cloudflare": "^10.11.0",
"@sentry/react": "^10.13.0",
"@sentry/vite-plugin": "^4.3.0",
"@typescript-eslint/eslint-plugin": "^8.42.0",
Expand All @@ -79,7 +67,6 @@
"agents": "^0.1.1",
"chalk": "^5.6.2",
"class-variance-authority": "^0.7.1",
"cloudflare": "^4.5.0",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"date-fns": "^4.1.0",
Expand Down Expand Up @@ -120,8 +107,6 @@
"zod": "^3.25.76"
},
"devDependencies": {
"@cloudflare/vite-plugin": "^1.13.2",
"@cloudflare/vitest-pool-workers": "^0.8.70",
"@eslint/js": "^9.35.0",
"@types/node": "^22.9.0",
"@tailwindcss/typography": "^0.5.16",
Expand Down Expand Up @@ -149,8 +134,7 @@
"vite": "npm:rolldown-vite@^7.1.11",
"vite-plugin-monaco-editor": "^1.1.0",
"vite-plugin-node-polyfills": "^0.24.0",
"vitest": "^3.2.4",
"wrangler": "4.38.0"
"vitest": "^3.2.4"
},
"prettier": {
"singleQuote": true,
Expand Down
10 changes: 4 additions & 6 deletions src/components/header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import clsx from 'clsx';
import { CloudflareLogo } from './icons/logos';
import { GitBranchPlus } from 'lucide-react';
import { Link } from 'react-router';

export function Header({
Expand All @@ -15,11 +15,9 @@ export function Header({
)}
>
<h1 className="flex items-center gap-2 mx-4">
<Link to="/">
<CloudflareLogo
className="h-4 text-bg-bright-dim"
aria-label="Cloudflare v1"
/>
<Link to="/" className="flex items-center gap-2">
<GitBranchPlus className="h-6 w-6 text-primary" />
<span className="text-lg font-semibold">Octpus</span>
</Link>
</h1>
<div className="flex-1"></div>
Expand Down
20 changes: 10 additions & 10 deletions src/components/shared/AppCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,13 @@ const AppMetadata = ({
<div className="flex items-center gap-2">
<Avatar className="h-8 w-8">
<AvatarImage src={app.userAvatar || undefined} />
<AvatarFallback className="text-[10px] bg-gradient-to-br from-red-200 to-red-300 font-semibold">
<AvatarFallback className="text-[10px] bg-gradient-to-br from-primary to-accent text-white font-semibold">
{app.userName?.charAt(0).toUpperCase() || '?'}
</AvatarFallback>
</Avatar>
</div>
)}
<div className="flex flex-col line-clamp-1 gap-1 w-full text-text-primary group-hover:text-bg-2 ">
<div className="flex flex-col line-clamp-1 gap-1 w-full text-text-primary group-hover:text-white ">
<span className="truncate text-ellipsis max-w-60 font-medium">
{app.title}
</span>
Expand All @@ -299,7 +299,7 @@ const AppMetadata = ({
const deploymentStatus = getDeploymentStatusInfo(app);
return (
<div className='flex flex-col'>
<span className="truncate text-ellipsis max-w-60 font-medium group-hover:text-bg-2">
<span className="truncate text-ellipsis max-w-60 font-medium group-hover:text-white">
{app.title}
</span>
<div className="flex items-center gap-2.5 text-sm">
Expand Down Expand Up @@ -333,7 +333,7 @@ const AppMetadata = ({
'text-green-400' &&
'text-green-600',
deploymentStatus.color ===
'text-gray-500' && 'text-gray-600 group-hover:text-bg-2',
'text-gray-500' && 'text-gray-600 group-hover:text-white',
deploymentStatus.color ===
'text-gray-500' &&
'text-text-tertiary',
Expand All @@ -345,7 +345,7 @@ const AppMetadata = ({
<span className="text-text-tertiary/60">•</span>
</>
)}
<span className="text-xs text-text-tertiary/80 group-hover:text-bg-1 font-medium">
<span className="text-xs text-text-tertiary/80 group-hover:text-white font-medium">
Updated{' '}
{isUserApp(app)
? app.updatedAtFormatted
Expand Down Expand Up @@ -423,12 +423,12 @@ export const AppCard = React.memo<AppCardProps>(
>
<Card
className={cn(
'h-full transition-all duration-300 ease-out cursor-pointer group relative overflow-hidden rounded-md p-2 bg-bg-1 hover:!bg-text hover:dark:!bg-text-primary',
'h-full transition-all duration-300 ease-out cursor-pointer group relative overflow-hidden rounded-md p-2 bg-bg-1 hover:!bg-primary',
'border border-border-primary hover:border-border-primary/60',
)}
>
{/* Enhanced Preview Section with High-Quality Rendering */}
<div className="relative aspect-[16/9] rounded-lg overflow-hidden bg-gradient-to-br from-red-50 to-red-100 dark:from-red-950/20 dark:to-orange-900/20">
<div className="relative aspect-[16/9] rounded-lg overflow-hidden bg-gradient-to-br from-primary/10 to-accent/10">
{app.screenshotUrl ? (
<img
src={app.screenshotUrl}
Expand Down Expand Up @@ -508,13 +508,13 @@ export const AppCard = React.memo<AppCardProps>(
? 'hidden opacity-0'
: 'opacity-100',
// Enhanced placeholder design
'bg-gradient-to-br from-red-50 via-red-100/80 to-red-200/60 dark:from-red-950/30 dark:via-red-900/20 dark:to-red-800/10',
'bg-gradient-to-br from-primary/10 via-primary/5 to-accent/10',
)}
>
<div className="flex flex-col items-center gap-3 text-red-400/70 dark:text-red-500/50">
<div className="flex flex-col items-center gap-3 text-primary/70 dark:text-primary/50">
<div className="relative">
<Code2 className="h-12 w-12 drop-shadow-sm" />
<div className="absolute inset-0 bg-gradient-to-t from-red-200/30 to-transparent rounded blur-sm" />
<div className="absolute inset-0 bg-gradient-to-t from-accent/30 to-transparent rounded blur-sm" />
</div>
<div className="text-xs font-medium text-center px-4 opacity-60">
Preview Unavailable
Expand Down
6 changes: 3 additions & 3 deletions src/components/shared/AppListContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const AppListContainer: React.FC<AppListContainerProps> = ({
return (
<div className="flex items-center py-20">
<div className="text-center">
<Loader2 className="h-8 w-8 animate-spin mx-auto mb-4 text-text-tertiary" />
<Loader2 className="h-8 w-8 animate-spin mx-auto mb-4 text-primary" />
<p className="text-neutral-50">Loading apps...</p>
</div>
</div>
Expand Down Expand Up @@ -135,7 +135,7 @@ export const AppListContainer: React.FC<AppListContainerProps> = ({

return (
<div className="text-center py-20">
<Code2 className="h-16 w-16 mx-auto mb-4 text-text-tertiary" />
<Code2 className="h-16 w-16 mx-auto mb-4 text-primary" />
<h3 className="text-xl font-semibold mb-2 text-text-secondary">
{emptyStateContent.title}
</h3>
Expand Down Expand Up @@ -176,7 +176,7 @@ export const AppListContainer: React.FC<AppListContainerProps> = ({

{loadingMore && (
<div className="flex justify-center mt-8">
<div className="flex items-center gap-2 text-text-tertiary">
<div className="flex items-center gap-2 text-primary">
<Loader2 className="h-4 w-4 animate-spin" />
<span className="text-sm">Loading more apps...</span>
</div>
Expand Down
10 changes: 5 additions & 5 deletions src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ const buttonVariants = cva(
variants: {
variant: {
default:
"bg-text-secondary text-bg-3 shadow-xs hover:bg-text-secondary/90",
"bg-primary text-white shadow-xs hover:bg-primary/90",
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"border bg-bg-3 dark:bg-bg-2 shadow-xs hover:bg-bg-4 hover:text-text-secondary dark:border-bg-4",
"border border-primary bg-transparent shadow-xs hover:bg-primary/10 text-primary",
secondary:
"bg-bg-2 text-text-secondary shadow-xs hover:bg-bg-2/80",
"bg-accent text-white shadow-xs hover:bg-accent/90",
ghost:
"hover:bg-accent hover:text-text-secondary dark:hover:bg-accent/50 text-text-primary",
link: "text-text-primary underline-offset-4 hover:underline",
"hover:bg-primary/10 text-primary",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
Expand Down
Loading