,
+ color: "text-blue-400"
+ },
+ {
+ label: "Active Messages",
+ value: analytics.messages_sent || 0,
+ change: 12,
+ icon: ,
+ color: "text-blue-400"
+ },
+ {
+ label: "Active Messages",
+ value: 48,
+ change: 12,
+ icon: Track your growth and engagement
+{stat.label}
+{stat.value}
+{data.date}
+{data.date}
+{metric.label}
+{metric.value}
+{metric.change}
+
+ by {selectedSnippet.creator}
+ + {/* Language & Category */} +{file.name}
++ {file.type === "file" && file.language && ( + <> + {file.language.toUpperCase()} •{" "} + > + )} + {formatFileSize(file.size)} • {file.modified} +
+Size: {formatFileSize(selectedFile.size)}
+Modified: {selectedFile.modified}
+ {selectedFile.language && ( +Language: {selectedFile.language.toUpperCase()}
+ )} +Balance
+{balance} LP
+by {listing.seller}
+{seller}
+★★★★★
+ +{msg.content}
+ + {msg.timestamp} + ++ {unreadCount > 0 ? `${unreadCount} unread` : "All caught up!"} +
+No {filterType ? `${filterType}` : ""} notifications
+{notification.description}
+{formatTime(notification.timestamp)}
+, component: "codegallery", defaultWidth: 900, defaultHeight: 650 },
{ id: "drives", title: "My Computer", icon: , component: "codegallery", defaultWidth: 900, defaultHeight: 650 },
{ id: "drives", title: "My Computer", icon: + {project.description} +
+ + {/* Progress Bar */} +{project.description}
+{project.description}
+Push Notifications
+Get alerts for important events
+Email Notifications
+Receive email digests
+Sound Effects
+Play notification sounds
+Auto-save
+Automatically save your work
+user@example.com
+Member Since
+December 23, 2025
+ - Execute JavaScript code
+ run - Run code from Lab
+ history - Show command history
+ exit - Exit terminal`,
+ timestamp: Date.now(),
+ },
+ ]);
+ break;
+
+ case 'clear':
+ setLines([]);
+ break;
+
+ case 'history':
+ setLines((prev) => [
+ ...prev,
+ {
+ type: 'output',
+ content: commandHistory.join('\n') || '(empty)',
+ timestamp: Date.now(),
+ },
+ ]);
+ break;
+
+ case 'execute':
+ const code = parts.slice(1).join(' ');
+ if (code) {
+ executeCode(code, 'javascript');
} else {
- clearInterval(interval);
- setTimeout(() => {
- setMode("quarantined");
- setLogs(prev => [
- ...prev,
- "",
- "> AEGIS INTERVENTION: PROTOCOL OMEGA",
- "> THREAT ISOLATED.",
- "> CONNECTION SEVERED.",
- "> SYSTEM RESTORED TO SAFE STATE."
- ]);
- }, 1000);
+ setLines((prev) => [
+ ...prev,
+ {
+ type: 'error',
+ content: 'Usage: execute ',
+ timestamp: Date.now(),
+ },
+ ]);
}
- }, 300);
+ break;
+
+ case 'run':
+ setLines((prev) => [
+ ...prev,
+ {
+ type: 'output',
+ content: '▸ Open Lab to run files',
+ timestamp: Date.now(),
+ },
+ ]);
+ break;
+
+ case 'exit':
+ setLines((prev) => [
+ ...prev,
+ {
+ type: 'system',
+ content: '▸ Type "help" to see available commands',
+ timestamp: Date.now(),
+ },
+ ]);
+ break;
+
+ default:
+ setLines((prev) => [
+ ...prev,
+ {
+ type: 'error',
+ content: `Command not found: ${command}. Type "help" for available commands.`,
+ timestamp: Date.now(),
+ },
+ ]);
+ }
+
+ setCommandHistory((prev) => [...prev, trimmed]);
+ setInput("");
+ setHistoryIndex(-1);
};
- const resetSystem = () => {
- setMode("normal");
- setLogs([
- "> SYSTEM REBOOT...",
- "> AEGIS CORE: ........................... [ ACTIVE ]",
- "> READY."
- ]);
+ const handleKeyDown = (e: React.KeyboardEvent) => {
+ if (e.key === 'Enter') {
+ processCommand(input);
+ } else if (e.key === 'ArrowUp') {
+ e.preventDefault();
+ const newIndex = historyIndex + 1;
+ if (newIndex < commandHistory.length) {
+ setHistoryIndex(newIndex);
+ setInput(commandHistory[commandHistory.length - 1 - newIndex]);
+ }
+ } else if (e.key === 'ArrowDown') {
+ e.preventDefault();
+ if (historyIndex > 0) {
+ const newIndex = historyIndex - 1;
+ setHistoryIndex(newIndex);
+ setInput(commandHistory[commandHistory.length - 1 - newIndex]);
+ } else if (historyIndex === 0) {
+ setHistoryIndex(-1);
+ setInput("");
+ }
+ }
};
return (
-
-
- {/* Top Bar (IDE Style) */}
-
+
+ {/* Header */}
+
-
+
-
-
- {mode === "attack" ? "AEGIS ALERT // UNDER ATTACK" : "AeThex Terminal v4.2"}
-
- {mode === "normal" && [ STATUS: ONLINE ]}
- {mode === "attack" && [ STATUS: CRITICAL ]}
- {mode === "quarantined" && [ STATUS: SECURE ]}
+
+ AeThex Terminal v4.2
+
+ [ ONLINE ]
+
-
- {/* Simulation Controls */}
- {mode === "normal" && (
-
- )}
- {mode === "quarantined" && (
-
- )}
+
+
-
- {/* Red Alert Overlay */}
-
- {mode === "attack" && (
-
-
-
-
- Threat Detected
-
-
- )}
-
-
- {/* Sidebar */}
-
- Explorer
-
- Project_Titan
- src
-
- main.verse
-
-
-
-
- Security Layer
-
-
- Aegis Core
-
- {mode === 'attack' ? : }
- {mode === 'attack' ? 'INTERVENING' : 'ACTIVE'}
-
-
-
-
-
-
- {/* Main Editor Area */}
-
-
- {/* Code Editor Mockup */}
-
-
- {Array.from({length: 20}).map((_, i) => (
- {i + 30}
- ))}
-
-
- {/* Code Content */}
-
- # User Input Handler
- class InputHandler:
- def HandleUserInput(Input: string): void =
- # Validate input length
- if (Input.Length > 100):
- return
-
- # Process user data
- LogUserActivity(Input)
-
-
- {mode === "quarantined" && (
-
-
-
- THREAT NEUTRALIZED
-
- Malicious code injection prevented by Aegis Core.
- The session has been sanitized.
-
-
-
- )}
-
-
- {/* Terminal Output */}
-
-
- TERMINAL
-
-
-
- {logs.map((log, i) => (
-
- {log}
-
- ))}
-
-
-
+ {/* Terminal Output */}
+
+ {lines.map((line, i) => (
+
+ {line.content.split('\n').map((part, idx) => (
+ {part}
+ ))}
+
+ ))}
+
+
+ {/* Input Bar */}
+
+
+ ▸
+ setInput(e.target.value)}
+ onKeyDown={handleKeyDown}
+ placeholder="Type command... (help for list)"
+ className="flex-1 bg-[#0a0a0c] border-0 text-[#a9b7c6] placeholder-[#555] focus:ring-0 focus:outline-none font-mono text-xs"
+ disabled={isExecuting}
+ autoFocus
+ />
+ {isExecuting && (
+ executing...
+ )}
diff --git a/migrations/0001_new_apps_expansion.sql b/migrations/0001_new_apps_expansion.sql
new file mode 100644
index 0000000..9b9b80a
--- /dev/null
+++ b/migrations/0001_new_apps_expansion.sql
@@ -0,0 +1,167 @@
+-- New tables for AeThex-OS app expansion
+-- Migration: 0001_new_apps_expansion.sql
+
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "messages" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "sender_id" varchar NOT NULL,
+ "recipient_id" varchar NOT NULL,
+ "content" text NOT NULL,
+ "read" boolean DEFAULT false,
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now()
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "marketplace_listings" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "seller_id" varchar NOT NULL,
+ "title" text NOT NULL,
+ "description" text,
+ "price" integer NOT NULL,
+ "category" varchar DEFAULT 'code' NOT NULL,
+ "tags" json DEFAULT '[]'::json,
+ "image_url" text,
+ "content_url" text,
+ "is_featured" boolean DEFAULT false,
+ "purchase_count" integer DEFAULT 0,
+ "views" integer DEFAULT 0,
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now()
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "workspace_settings" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar NOT NULL,
+ "theme" varchar DEFAULT 'dark',
+ "font_size" integer DEFAULT 14,
+ "show_sidebar" boolean DEFAULT true,
+ "notifications_enabled" boolean DEFAULT true,
+ "email_notifications" boolean DEFAULT true,
+ "auto_save" boolean DEFAULT true,
+ "word_wrap" boolean DEFAULT true,
+ "show_minimap" boolean DEFAULT true,
+ "privacy_profile_visible" boolean DEFAULT true,
+ "privacy_activity_visible" boolean DEFAULT true,
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now(),
+ CONSTRAINT "workspace_settings_user_id_unique" UNIQUE("user_id")
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "files" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar NOT NULL,
+ "name" text NOT NULL,
+ "path" text NOT NULL,
+ "content" text,
+ "size" integer DEFAULT 0,
+ "language" varchar,
+ "parent_id" varchar,
+ "is_folder" boolean DEFAULT false,
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now()
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "notifications" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar NOT NULL,
+ "type" varchar DEFAULT 'system' NOT NULL,
+ "title" text NOT NULL,
+ "description" text,
+ "read" boolean DEFAULT false,
+ "action_url" text,
+ "created_at" timestamp DEFAULT now()
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "user_analytics" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar NOT NULL,
+ "total_xp" integer DEFAULT 0,
+ "projects_completed" integer DEFAULT 0,
+ "achievements_unlocked" integer DEFAULT 0,
+ "messages_sent" integer DEFAULT 0,
+ "marketplace_purchases" integer DEFAULT 0,
+ "code_snippets_shared" integer DEFAULT 0,
+ "daily_active_minutes" integer DEFAULT 0,
+ "last_active" timestamp DEFAULT now(),
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now(),
+ CONSTRAINT "user_analytics_user_id_unique" UNIQUE("user_id")
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "code_gallery" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "creator_id" varchar NOT NULL,
+ "title" text NOT NULL,
+ "description" text,
+ "code" text NOT NULL,
+ "language" varchar NOT NULL,
+ "category" varchar DEFAULT 'snippet',
+ "tags" json DEFAULT '[]'::json,
+ "likes" integer DEFAULT 0,
+ "views" integer DEFAULT 0,
+ "is_public" boolean DEFAULT true,
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now()
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "documentation" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "title" text NOT NULL,
+ "slug" varchar NOT NULL,
+ "content" text NOT NULL,
+ "category" varchar DEFAULT 'guide',
+ "order" integer DEFAULT 0,
+ "is_published" boolean DEFAULT true,
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now(),
+ CONSTRAINT "documentation_slug_unique" UNIQUE("slug")
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "custom_apps" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "creator_id" varchar NOT NULL,
+ "name" text NOT NULL,
+ "description" text,
+ "config" json DEFAULT '{}'::json,
+ "is_public" boolean DEFAULT false,
+ "install_count" integer DEFAULT 0,
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now()
+);
+--> statement-breakpoint
+CREATE TABLE IF NOT EXISTS "projects" (
+ "id" varchar PRIMARY KEY NOT NULL,
+ "user_id" varchar NOT NULL,
+ "title" text NOT NULL,
+ "description" text,
+ "status" varchar DEFAULT 'planning',
+ "progress" integer DEFAULT 0,
+ "tech_stack" json DEFAULT '[]'::json,
+ "live_url" text,
+ "github_url" text,
+ "start_date" timestamp DEFAULT now(),
+ "end_date" timestamp,
+ "created_at" timestamp DEFAULT now(),
+ "updated_at" timestamp DEFAULT now()
+);
+--> statement-breakpoint
+-- Create indexes for better query performance
+CREATE INDEX IF NOT EXISTS "messages_sender_id_idx" ON "messages" ("sender_id");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "messages_recipient_id_idx" ON "messages" ("recipient_id");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "marketplace_listings_seller_id_idx" ON "marketplace_listings" ("seller_id");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "marketplace_listings_category_idx" ON "marketplace_listings" ("category");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "files_user_id_idx" ON "files" ("user_id");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "files_parent_id_idx" ON "files" ("parent_id");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "notifications_user_id_idx" ON "notifications" ("user_id");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "user_analytics_user_id_idx" ON "user_analytics" ("user_id");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "code_gallery_creator_id_idx" ON "code_gallery" ("creator_id");
+--> statement-breakpoint
+CREATE INDEX IF NOT EXISTS "projects_user_id_idx" ON "projects" ("user_id");
diff --git a/migrations/meta/_journal.json b/migrations/meta/_journal.json
index b210484..ee42c12 100644
--- a/migrations/meta/_journal.json
+++ b/migrations/meta/_journal.json
@@ -8,6 +8,13 @@
"when": 1766373949237,
"tag": "0000_worried_mastermind",
"breakpoints": true
+ },
+ {
+ "idx": 1,
+ "version": "7",
+ "when": 1735020000000,
+ "tag": "0001_new_apps_expansion",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/script/run-migration.ts b/script/run-migration.ts
new file mode 100644
index 0000000..d8753b6
--- /dev/null
+++ b/script/run-migration.ts
@@ -0,0 +1,50 @@
+import { readFile } from 'fs/promises';
+import pg from 'pg';
+import dotenv from 'dotenv';
+
+dotenv.config();
+
+const { Client } = pg;
+
+async function runMigration() {
+ const client = new Client({
+ connectionString: process.env.DATABASE_URL,
+ });
+
+ try {
+ await client.connect();
+ console.log('Connected to database');
+
+ const sql = await readFile('./migrations/0001_new_apps_expansion.sql', 'utf-8');
+
+ // Split by statement breakpoints and execute each statement
+ const statements = sql
+ .split('--> statement-breakpoint')
+ .map(s => s.trim())
+ .filter(s => s.length > 0 && !s.startsWith('--'));
+
+ console.log(`Executing ${statements.length} statements...`);
+
+ for (const [index, statement] of statements.entries()) {
+ try {
+ await client.query(statement);
+ console.log(`✓ Statement ${index + 1}/${statements.length} executed`);
+ } catch (error: any) {
+ console.error(`✗ Statement ${index + 1} failed:`, error.message);
+ // Continue on duplicate errors
+ if (!error.message.includes('already exists')) {
+ throw error;
+ }
+ }
+ }
+
+ console.log('\n✅ Migration completed successfully!');
+ } catch (error) {
+ console.error('\n❌ Migration failed:', error);
+ process.exit(1);
+ } finally {
+ await client.end();
+ }
+}
+
+runMigration();
diff --git a/shared/schema.ts b/shared/schema.ts
index c006a00..1516f7a 100644
--- a/shared/schema.ts
+++ b/shared/schema.ts
@@ -397,3 +397,226 @@ export const insertAethexEventSchema = createInsertSchema(aethex_events).omit({
export type InsertAethexEvent = z.infer;
export type AethexEvent = typeof aethex_events.$inferSelect;
+
+// ============ NEW FEATURE TABLES ============
+
+// Messages table for Messaging app
+export const messages = pgTable("messages", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ sender_id: varchar("sender_id").notNull(),
+ recipient_id: varchar("recipient_id").notNull(),
+ content: text("content").notNull(),
+ read: boolean("read").default(false),
+ created_at: timestamp("created_at").defaultNow(),
+ updated_at: timestamp("updated_at").defaultNow(),
+});
+
+export const insertMessageSchema = createInsertSchema(messages).omit({
+ created_at: true,
+ updated_at: true,
+});
+
+export type InsertMessage = z.infer;
+export type Message = typeof messages.$inferSelect;
+
+// Marketplace Listings table
+export const marketplace_listings = pgTable("marketplace_listings", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ seller_id: varchar("seller_id").notNull(),
+ title: text("title").notNull(),
+ description: text("description"),
+ category: text("category").notNull(), // 'achievement', 'code', 'service', 'credential'
+ price: integer("price").notNull(), // in loyalty points
+ image_url: text("image_url"),
+ status: text("status").default("active"), // 'active', 'sold', 'removed'
+ tags: json("tags").$type().default([]),
+ created_at: timestamp("created_at").defaultNow(),
+ updated_at: timestamp("updated_at").defaultNow(),
+ purchase_count: integer("purchase_count").default(0),
+});
+
+export const insertMarketplaceListingSchema = createInsertSchema(marketplace_listings).omit({
+ created_at: true,
+ updated_at: true,
+});
+
+export type InsertMarketplaceListing = z.infer;
+export type MarketplaceListing = typeof marketplace_listings.$inferSelect;
+
+// Marketplace Transactions table
+export const marketplace_transactions = pgTable("marketplace_transactions", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ buyer_id: varchar("buyer_id").notNull(),
+ seller_id: varchar("seller_id").notNull(),
+ listing_id: varchar("listing_id").notNull(),
+ amount: integer("amount").notNull(),
+ status: text("status").default("completed"), // 'pending', 'completed', 'refunded'
+ created_at: timestamp("created_at").defaultNow(),
+});
+
+export const insertMarketplaceTransactionSchema = createInsertSchema(marketplace_transactions).omit({
+ created_at: true,
+});
+
+export type InsertMarketplaceTransaction = z.infer;
+export type MarketplaceTransaction = typeof marketplace_transactions.$inferSelect;
+
+// Workspace Settings table
+export const workspace_settings = pgTable("workspace_settings", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ user_id: varchar("user_id").notNull().unique(),
+ theme: text("theme").default("dark"), // 'dark', 'light', 'auto'
+ font_size: text("font_size").default("medium"), // 'small', 'medium', 'large'
+ editor_font: text("editor_font").default("Monaco"),
+ sidebar_collapsed: boolean("sidebar_collapsed").default(false),
+ notifications_enabled: boolean("notifications_enabled").default(true),
+ email_notifications: boolean("email_notifications").default(true),
+ sound_enabled: boolean("sound_enabled").default(true),
+ auto_save: boolean("auto_save").default(true),
+ privacy_level: text("privacy_level").default("private"), // 'private', 'friends', 'public'
+ created_at: timestamp("created_at").defaultNow(),
+ updated_at: timestamp("updated_at").defaultNow(),
+});
+
+export const insertWorkspaceSettingsSchema = createInsertSchema(workspace_settings).omit({
+ created_at: true,
+ updated_at: true,
+});
+
+export type InsertWorkspaceSettings = z.infer;
+export type WorkspaceSettings = typeof workspace_settings.$inferSelect;
+
+// Files table for File Manager
+export const files = pgTable("files", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ user_id: varchar("user_id").notNull(),
+ name: text("name").notNull(),
+ type: text("type").notNull(), // 'file', 'folder'
+ path: text("path").notNull(),
+ size: integer("size"), // in bytes
+ mime_type: text("mime_type"),
+ parent_id: varchar("parent_id"), // for folders
+ content: text("content"), // for code files
+ language: text("language"), // 'typescript', 'javascript', etc
+ created_at: timestamp("created_at").defaultNow(),
+ updated_at: timestamp("updated_at").defaultNow(),
+});
+
+export const insertFileSchema = createInsertSchema(files).omit({
+ created_at: true,
+ updated_at: true,
+});
+
+export type InsertFile = z.infer;
+export type File = typeof files.$inferSelect;
+
+// Notifications table
+export const notifications = pgTable("notifications", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ user_id: varchar("user_id").notNull(),
+ type: text("type").notNull(), // 'message', 'achievement', 'purchase', 'event', 'mention'
+ title: text("title").notNull(),
+ content: text("content"),
+ related_id: varchar("related_id"), // link to source (message_id, achievement_id, etc)
+ read: boolean("read").default(false),
+ created_at: timestamp("created_at").defaultNow(),
+});
+
+export const insertNotificationSchema = createInsertSchema(notifications).omit({
+ created_at: true,
+});
+
+export type InsertNotification = z.infer;
+export type Notification = typeof notifications.$inferSelect;
+
+// User Analytics table
+export const user_analytics = pgTable("user_analytics", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ user_id: varchar("user_id").notNull(),
+ total_xp_earned: integer("total_xp_earned").default(0),
+ total_projects: integer("total_projects").default(0),
+ total_achievements: integer("total_achievements").default(0),
+ messages_sent: integer("messages_sent").default(0),
+ marketplace_purchases: integer("marketplace_purchases").default(0),
+ marketplace_sales: integer("marketplace_sales").default(0),
+ events_attended: integer("events_attended").default(0),
+ last_active: timestamp("last_active"),
+ created_at: timestamp("created_at").defaultNow(),
+ updated_at: timestamp("updated_at").defaultNow(),
+});
+
+export const insertUserAnalyticsSchema = createInsertSchema(user_analytics).omit({
+ created_at: true,
+ updated_at: true,
+});
+
+export type InsertUserAnalytics = z.infer;
+export type UserAnalytics = typeof user_analytics.$inferSelect;
+
+// Code Gallery table
+export const code_gallery = pgTable("code_gallery", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ creator_id: varchar("creator_id").notNull(),
+ title: text("title").notNull(),
+ description: text("description"),
+ code: text("code").notNull(),
+ language: text("language").notNull(),
+ tags: json("tags").$type().default([]),
+ likes: integer("likes").default(0),
+ views: integer("views").default(0),
+ is_public: boolean("is_public").default(true),
+ category: text("category"), // 'snippet', 'algorithm', 'component', 'utility'
+ created_at: timestamp("created_at").defaultNow(),
+ updated_at: timestamp("updated_at").defaultNow(),
+});
+
+export const insertCodeGallerySchema = createInsertSchema(code_gallery).omit({
+ created_at: true,
+ updated_at: true,
+});
+
+export type InsertCodeGallery = z.infer;
+export type CodeGallery = typeof code_gallery.$inferSelect;
+
+// Documentation pages table
+export const documentation = pgTable("documentation", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ slug: text("slug").notNull().unique(),
+ title: text("title").notNull(),
+ content: text("content").notNull(),
+ category: text("category").notNull(), // 'getting-started', 'api', 'features', 'tutorials'
+ order: integer("order").default(0),
+ created_at: timestamp("created_at").defaultNow(),
+ updated_at: timestamp("updated_at").defaultNow(),
+});
+
+export const insertDocumentationSchema = createInsertSchema(documentation).omit({
+ created_at: true,
+ updated_at: true,
+});
+
+export type InsertDocumentation = z.infer;
+export type Documentation = typeof documentation.$inferSelect;
+
+// App Builder table
+export const custom_apps = pgTable("custom_apps", {
+ id: varchar("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
+ creator_id: varchar("creator_id").notNull(),
+ name: text("name").notNull(),
+ description: text("description"),
+ icon: text("icon"),
+ config: json("config"), // JSON config for builder
+ status: text("status").default("draft"), // 'draft', 'published'
+ is_public: boolean("is_public").default(false),
+ installations: integer("installations").default(0),
+ created_at: timestamp("created_at").defaultNow(),
+ updated_at: timestamp("updated_at").defaultNow(),
+});
+
+export const insertCustomAppSchema = createInsertSchema(custom_apps).omit({
+ created_at: true,
+ updated_at: true,
+});
+
+export type InsertCustomApp = z.infer;
+export type CustomApp = typeof custom_apps.$inferSelect;