diff --git a/.gitignore b/.gitignore
index 04c01ba..7b11b3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
node_modules/
-dist/
\ No newline at end of file
+dist/
+
+# Business documentation (contains sensitive info)
+docs/
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ac58b6f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,47 @@
+MIT License
+
+Copyright (c) 2024 Rohith Gilla
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+---
+
+## Commercial Use License
+
+While the source code is MIT licensed, pre-built binaries require a license
+for commercial use. Commercial use is defined as using data-peek for
+revenue-generating or work-related activities within a for-profit organization
+of two or more people.
+
+### Free Use (No License Required)
+- Personal projects and learning
+- Open source contributors
+- Students and educators
+- Registered non-profit organizations
+- Solo founders (company of one)
+
+### License Required
+- Developers at companies with 2+ people
+- Freelancers billing clients
+- Agencies using for client work
+
+This licensing model is inspired by Yaak and other sustainable indie software
+projects that balance open source values with sustainable development.
+
+Learn more at https://data-peek.dev/license
diff --git a/apps/web/src/components/marketing/faq.tsx b/apps/web/src/components/marketing/faq.tsx
index 10c89b4..a99055d 100644
--- a/apps/web/src/components/marketing/faq.tsx
+++ b/apps/web/src/components/marketing/faq.tsx
@@ -7,42 +7,52 @@ const faqs = [
{
question: 'Is data-peek really free?',
answer:
- 'Yes! The free tier is fully functional with 2 connections, 50 query history items, and 3 tabs. No credit card required, no time limits. The Pro license unlocks unlimited everything plus advanced features like inline editing and query plans.',
+ 'Yes! data-peek is free for personal use with all features unlocked. No credit card required, no time limits, no feature restrictions. A license is only required if you use it for commercial purposes at a for-profit company with 2+ people.',
},
{
- question: 'What does "pay once, own forever" mean?',
+ question: 'What counts as commercial use?',
answer:
- 'Unlike subscription software, you pay $29 once and get a perpetual license. The license includes 1 year of updates. After that year, you can keep using the version you have forever, or renew for another year of updates at a discounted rate.',
+ 'Commercial use means using data-peek for work-related activities in a for-profit organization of 2+ people. This includes developers at startups/companies, freelancers billing clients, and agencies doing client work. Solo founders (company of one) are free!',
},
{
- question: 'How many devices can I use with one license?',
+ question: 'Is data-peek open source?',
answer:
- 'One Pro license includes 3 device activations. You can use data-peek on your work laptop, home computer, and one more device. Need more? Contact us for volume licensing.',
+ 'Yes! The source code is MIT licensed on GitHub. You can view, modify, fork, and build it yourself for any purpose. Pre-built binaries require a license for commercial use — this is how we sustain development.',
},
{
- question: 'Does data-peek work offline?',
+ question: 'What does "perpetual fallback" mean?',
answer:
- "Absolutely. data-peek runs entirely on your machine. We validate licenses online during activation, but after that, you can work offline. There's a grace period for license revalidation.",
+ 'When you buy a Pro license ($29/year), you get 1 year of updates. If you don\'t renew, you keep your current version forever — it doesn\'t stop working. You just won\'t receive future updates. Renew anytime to get the latest.',
},
{
- question: 'What databases are supported?',
+ question: "I'm a student. Can I use it for free?",
answer:
- "Currently, data-peek is PostgreSQL-only. We're laser-focused on making the best Postgres experience possible. MySQL and SQLite support are planned for future releases.",
+ 'Absolutely! Students and educators can use data-peek for free, even for school projects. Just reach out on X (@gillarohith) or email gillarohith1@gmail.com and we\'ll hook you up with a free license. Learning should never have barriers.',
+ },
+ {
+ question: 'How does the honor system work?',
+ answer:
+ 'We trust you. There\'s no DRM, no aggressive license checks, no "you\'ve been logged out" surprises. If you\'re using it commercially, we ask that you pay for a license. Inspired by Yaak and other sustainable indie software.',
+ },
+ {
+ question: 'How many devices can I use?',
+ answer:
+ 'Each license includes 3 device activations. Use it on your work laptop, home computer, and one more device. Need more? Just reach out.',
},
{
question: 'Is my data safe?',
answer:
- 'Yes. data-peek never sends your data anywhere. All queries run directly from your machine to your database. Connection credentials are encrypted locally. We have no telemetry, no analytics, no tracking.',
+ 'Yes. data-peek runs entirely on your machine. All queries go directly to your database — we never see your data. Connection credentials are encrypted locally. No telemetry, no analytics, no tracking.',
+ },
+ {
+ question: 'What databases are supported?',
+ answer:
+ 'Currently PostgreSQL and MySQL. We\'re laser-focused on making the best database experience possible. SQLite and more databases are planned for future releases.',
},
{
question: 'Can I get a refund?',
answer:
- "Yes, we offer a 14-day money-back guarantee. If data-peek isn't right for you, just email us and we'll refund your purchase, no questions asked.",
- },
- {
- question: 'Do you offer team or enterprise licenses?',
- answer:
- "Not yet, but we're working on it! Cloud sync and team features are coming soon. Sign up for our newsletter to be notified when they launch.",
+ 'Yes, 30-day money-back guarantee, no questions asked. If data-peek isn\'t right for you, just email us.',
},
]
diff --git a/apps/web/src/components/marketing/footer.tsx b/apps/web/src/components/marketing/footer.tsx
index c2f5c09..43bdc00 100644
--- a/apps/web/src/components/marketing/footer.tsx
+++ b/apps/web/src/components/marketing/footer.tsx
@@ -57,7 +57,7 @@ export function Footer() {
- {/* Early Bird Badge */}
-
-
+ {/* Early Bird + Open Source Badge */}
+
+
Early Bird — 70% off
+
+
+ Open Source
+
{/* Main Headline */}
@@ -52,7 +56,7 @@ export function Hero() {
style={{ fontFamily: 'var(--font-body)' }}
>
A lightning-fast PostgreSQL client for developers who value simplicity.
- No bloat, no subscriptions, no BS.
+ Open source, free for personal use.
{/* Terminal-style feature highlight */}
@@ -70,7 +74,7 @@ export function Hero() {
- pay once, own forever
+ all features free
diff --git a/apps/web/src/components/marketing/pricing.tsx b/apps/web/src/components/marketing/pricing.tsx
index 00aa084..7e6ad52 100644
--- a/apps/web/src/components/marketing/pricing.tsx
+++ b/apps/web/src/components/marketing/pricing.tsx
@@ -1,23 +1,22 @@
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
-import { Check, X, Sparkles, ArrowRight } from 'lucide-react'
+import { Check, Heart, Github, ArrowRight, Sparkles } from 'lucide-react'
const plans = [
{
- name: 'Free',
+ name: 'Personal',
price: '$0',
period: 'forever',
- description: 'Perfect for trying out data-peek',
+ description: 'All features, personal use only',
features: [
- { text: '2 database connections', included: true },
- { text: '50 query history items', included: true },
- { text: '3 editor tabs', included: true },
- { text: '1 schema for ER diagrams', included: true },
- { text: 'CSV/JSON export', included: true },
- { text: 'Inline data editing', included: false },
- { text: 'Query execution plans', included: false },
- { text: 'Updates', included: false },
+ { text: 'All features unlocked', included: true },
+ { text: 'Unlimited connections', included: true },
+ { text: 'Unlimited query history', included: true },
+ { text: 'All future updates', included: true },
+ { text: 'Personal projects & learning', included: true },
+ { text: 'Open source contributors', included: true },
+ { text: 'Students & educators', included: true },
],
cta: 'Download Free',
href: '/download',
@@ -27,19 +26,17 @@ const plans = [
name: 'Pro',
price: '$29',
originalPrice: '$99',
- period: 'one-time',
- description: 'For developers who need the full power',
+ period: 'year',
+ description: 'For commercial use at work',
badge: 'Early Bird — 70% off',
features: [
- { text: 'Unlimited connections', included: true },
- { text: 'Unlimited query history', included: true },
- { text: 'Unlimited tabs', included: true },
- { text: 'Unlimited ER diagrams', included: true },
- { text: 'CSV/JSON export', included: true },
- { text: 'Inline data editing', included: true },
- { text: 'Query execution plans', included: true },
- { text: '1 year of updates', included: true },
+ { text: 'Everything in Personal', included: true },
+ { text: 'Commercial use allowed', included: true },
+ { text: 'Use at work & for clients', included: true },
+ { text: '1 year of updates included', included: true },
{ text: '3 device activations', included: true },
+ { text: 'Perpetual fallback license', included: true },
+ { text: '30-day money-back guarantee', included: true },
],
cta: 'Get Pro License',
href: '#buy',
@@ -66,15 +63,16 @@ export function Pricing() {
className="text-4xl md:text-5xl lg:text-6xl font-semibold tracking-tight mb-6"
style={{ fontFamily: 'var(--font-display)' }}
>
- Pay once.
+ Open source.
-
Own forever.
+
Pay for commercial use.
- No subscriptions, no recurring fees. One purchase, lifetime access.
+ Free for personal use. A license supports development and is required
+ for commercial use in for-profit organizations.
@@ -92,7 +90,7 @@ export function Pricing() {
{/* Badge */}
{plan.badge && (
-
+
{plan.badge}
@@ -128,22 +126,10 @@ export function Pricing() {
{plan.features.map((feature) => (
- {feature.included ? (
-
-
-
- ) : (
-
-
-
- )}
-
+
+
+
+
{feature.text}
@@ -166,20 +152,69 @@ export function Pricing() {
))}
- {/* Cloud Teaser */}
-
-
-
- Coming soon:
-
-
- Cloud sync & team features
-
+ {/* Honor System Notice */}
+
+
+
+
+
+
+
+ Honor System Licensing
+
+
+ Inspired by{' '}
+
+ Yaak
+ {' '}
+ and other sustainable indie software. No DRM, no aggressive enforcement.
+ We trust you to do the right thing.
+
+
+ Students: Use it free! Just reach out for a free license.
+
+
+ Questions?{' '}
+
+ @gillarohith
+ {' '}
+ or{' '}
+
+ gillarohith1@gmail.com
+
+
+
+
+ {/* Open Source Notice */}
+
+
+
+ View source on GitHub — MIT Licensed
+
+
)
diff --git a/docs/PLAN-table-designer.md b/docs/PLAN-table-designer.md
deleted file mode 100644
index bece7ae..0000000
--- a/docs/PLAN-table-designer.md
+++ /dev/null
@@ -1,570 +0,0 @@
-# Table Designer Feature - Implementation Plan
-
-## Overview
-
-This plan outlines the implementation of a comprehensive Table Designer feature for data-peek, enabling users to create new tables and modify existing tables through a dedicated tab interface with full PostgreSQL feature support.
-
-## Scope
-
-- **Create Table**: Full-featured table creation with columns, constraints, indexes
-- **Edit Table (ALTER TABLE)**: Add/drop/rename columns, modify types, manage constraints and indexes
-- **PostgreSQL Full Features**: Sequences, partitioning, inheritance, custom types, CHECK constraints, UNIQUE constraints
-
----
-
-## Phase 1: Shared Types & Data Models
-
-### File: `packages/shared/src/index.ts`
-
-Add new types for DDL operations:
-
-```typescript
-// PostgreSQL data types for dropdown
-export type PostgresDataType =
- | 'smallint' | 'integer' | 'bigint' | 'serial' | 'bigserial'
- | 'numeric' | 'real' | 'double precision' | 'money'
- | 'char' | 'varchar' | 'text'
- | 'bytea'
- | 'timestamp' | 'timestamptz' | 'date' | 'time' | 'timetz' | 'interval'
- | 'boolean'
- | 'uuid'
- | 'json' | 'jsonb'
- | 'xml'
- | 'point' | 'line' | 'lseg' | 'box' | 'path' | 'polygon' | 'circle'
- | 'cidr' | 'inet' | 'macaddr'
- | 'int4range' | 'int8range' | 'numrange' | 'tsrange' | 'tstzrange' | 'daterange'
- | 'custom' // For custom/enum types
-
-// Column definition for table designer
-export interface ColumnDefinition {
- id: string // Client-side tracking
- name: string
- dataType: PostgresDataType | string
- length?: number // For varchar(n), char(n)
- precision?: number // For numeric(p,s)
- scale?: number
- isNullable: boolean
- isPrimaryKey: boolean
- isUnique: boolean
- defaultValue?: string
- defaultType?: 'value' | 'expression' | 'sequence'
- sequenceName?: string // For nextval('sequence')
- checkConstraint?: string
- comment?: string
- collation?: string
- isArray?: boolean // For array types like text[]
-}
-
-// Constraint types
-export type ConstraintType = 'primary_key' | 'foreign_key' | 'unique' | 'check' | 'exclude'
-
-export interface ConstraintDefinition {
- id: string
- name?: string // Optional, auto-generated if not provided
- type: ConstraintType
- columns: string[]
- // Foreign key specific
- referencedSchema?: string
- referencedTable?: string
- referencedColumns?: string[]
- onUpdate?: 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT'
- onDelete?: 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT'
- // Check constraint specific
- checkExpression?: string
- // Exclude constraint specific (advanced)
- excludeElements?: Array<{ column: string; operator: string }>
- excludeUsing?: 'btree' | 'gist' | 'gin' | 'hash'
-}
-
-// Index definition
-export interface IndexDefinition {
- id: string
- name?: string
- columns: Array<{
- name: string
- order?: 'ASC' | 'DESC'
- nullsPosition?: 'FIRST' | 'LAST'
- }>
- isUnique: boolean
- method?: 'btree' | 'hash' | 'gist' | 'gin' | 'spgist' | 'brin'
- where?: string // Partial index condition
- include?: string[] // INCLUDE columns (covering index)
- concurrent?: boolean
-}
-
-// Table partitioning
-export interface PartitionDefinition {
- type: 'RANGE' | 'LIST' | 'HASH'
- columns: string[]
-}
-
-// Full table definition
-export interface TableDefinition {
- schema: string
- name: string
- columns: ColumnDefinition[]
- constraints: ConstraintDefinition[]
- indexes: IndexDefinition[]
- partition?: PartitionDefinition
- inherits?: string[] // Parent tables
- tablespace?: string
- comment?: string
- withOids?: boolean
- unlogged?: boolean
-}
-
-// ALTER TABLE operations
-export type AlterColumnOperation =
- | { type: 'add'; column: ColumnDefinition }
- | { type: 'drop'; columnName: string; cascade?: boolean }
- | { type: 'rename'; oldName: string; newName: string }
- | { type: 'set_type'; columnName: string; newType: string; using?: string }
- | { type: 'set_nullable'; columnName: string; nullable: boolean }
- | { type: 'set_default'; columnName: string; defaultValue: string | null }
- | { type: 'set_comment'; columnName: string; comment: string | null }
-
-export type AlterConstraintOperation =
- | { type: 'add_constraint'; constraint: ConstraintDefinition }
- | { type: 'drop_constraint'; name: string; cascade?: boolean }
- | { type: 'rename_constraint'; oldName: string; newName: string }
-
-export type AlterIndexOperation =
- | { type: 'create_index'; index: IndexDefinition }
- | { type: 'drop_index'; name: string; cascade?: boolean; concurrent?: boolean }
- | { type: 'rename_index'; oldName: string; newName: string }
- | { type: 'reindex'; name: string; concurrent?: boolean }
-
-export interface AlterTableBatch {
- schema: string
- table: string
- columnOperations: AlterColumnOperation[]
- constraintOperations: AlterConstraintOperation[]
- indexOperations: AlterIndexOperation[]
- renameTable?: string
- setSchema?: string
- comment?: string | null
-}
-
-// Result types
-export interface DDLResult {
- success: boolean
- executedSql: string[]
- errors?: string[]
-}
-
-// Metadata for UI
-export interface SequenceInfo {
- schema: string
- name: string
- dataType: string
- startValue: string
- increment: string
-}
-
-export interface CustomTypeInfo {
- schema: string
- name: string
- type: 'enum' | 'composite' | 'range' | 'domain'
- values?: string[] // For enums
-}
-```
-
----
-
-## Phase 2: DDL SQL Builder
-
-### New File: `apps/desktop/src/main/ddl-builder.ts`
-
-Create a dedicated builder for DDL statements:
-
-```typescript
-// Key functions to implement:
-export function buildCreateTable(definition: TableDefinition): ParameterizedQuery
-export function buildAlterTable(batch: AlterTableBatch): ParameterizedQuery[]
-export function buildDropTable(schema: string, table: string, cascade?: boolean): ParameterizedQuery
-export function buildCreateIndex(schema: string, table: string, index: IndexDefinition): ParameterizedQuery
-export function buildPreviewDDL(definition: TableDefinition): string // For UI preview
-export function buildAlterPreviewDDL(batch: AlterTableBatch): string[]
-```
-
-Key considerations:
-- Quote all identifiers properly
-- Handle reserved words
-- Escape string values in defaults
-- Support all PostgreSQL constraint syntax
-- Handle partial indexes with WHERE
-- Support expression indexes
-
----
-
-## Phase 3: IPC Handlers
-
-### File: `apps/desktop/src/main/index.ts`
-
-Add new IPC handlers:
-
-```typescript
-// Create table
-ipcMain.handle('db:create-table', async (_, { config, definition }) => {
- // Execute CREATE TABLE statement
- // Return DDLResult
-})
-
-// Alter table
-ipcMain.handle('db:alter-table', async (_, { config, batch }) => {
- // Execute ALTER TABLE statements in transaction
- // Return DDLResult
-})
-
-// Drop table
-ipcMain.handle('db:drop-table', async (_, { config, schema, table, cascade }) => {
- // Execute DROP TABLE
- // Return DDLResult
-})
-
-// Get table DDL (reverse engineer)
-ipcMain.handle('db:get-table-ddl', async (_, { config, schema, table }) => {
- // Query pg_catalog to reconstruct CREATE TABLE
- // Return TableDefinition
-})
-
-// Get available sequences
-ipcMain.handle('db:get-sequences', async (_, config) => {
- // Query pg_sequences
- // Return SequenceInfo[]
-})
-
-// Get custom types
-ipcMain.handle('db:get-types', async (_, config) => {
- // Query pg_type for enums, composites, etc.
- // Return CustomTypeInfo[]
-})
-
-// Preview DDL without executing
-ipcMain.handle('db:preview-ddl', async (_, { definition }) => {
- // Return generated SQL string
-})
-```
-
-### File: `apps/desktop/src/preload/index.ts`
-
-Update API exposure:
-
-```typescript
-const api = {
- // ... existing
- ddl: {
- createTable: (config, definition) => ipcRenderer.invoke('db:create-table', { config, definition }),
- alterTable: (config, batch) => ipcRenderer.invoke('db:alter-table', { config, batch }),
- dropTable: (config, schema, table, cascade) =>
- ipcRenderer.invoke('db:drop-table', { config, schema, table, cascade }),
- getTableDDL: (config, schema, table) =>
- ipcRenderer.invoke('db:get-table-ddl', { config, schema, table }),
- getSequences: (config) => ipcRenderer.invoke('db:get-sequences', config),
- getTypes: (config) => ipcRenderer.invoke('db:get-types', config),
- previewDDL: (definition) => ipcRenderer.invoke('db:preview-ddl', { definition })
- }
-}
-```
-
----
-
-## Phase 4: Tab Store Extension
-
-### File: `apps/desktop/src/renderer/src/stores/tab-store.ts`
-
-Add new tab type:
-
-```typescript
-export type TabType = 'query' | 'table-preview' | 'erd' | 'table-designer'
-
-export interface TableDesignerTab extends BaseTab {
- type: 'table-designer'
- schemaName: string
- tableName?: string // undefined for new table
- mode: 'create' | 'edit'
- isDirty: boolean
-}
-
-// New actions
-createTableDesignerTab: (connectionId: string, schemaName: string, tableName?: string) => string
-```
-
----
-
-## Phase 5: DDL Store
-
-### New File: `apps/desktop/src/renderer/src/stores/ddl-store.ts`
-
-Create Zustand store for table designer state:
-
-```typescript
-interface DDLState {
- // Per-tab state (keyed by tabId)
- tabState: Map
-
- // Actions
- initializeTab: (tabId: string, mode: 'create' | 'edit', definition?: TableDefinition) => void
-
- // Column operations
- addColumn: (tabId: string, column?: Partial) => void
- updateColumn: (tabId: string, columnId: string, updates: Partial) => void
- removeColumn: (tabId: string, columnId: string) => void
- reorderColumns: (tabId: string, startIndex: number, endIndex: number) => void
-
- // Constraint operations
- addConstraint: (tabId: string, constraint: ConstraintDefinition) => void
- updateConstraint: (tabId: string, constraintId: string, updates: Partial) => void
- removeConstraint: (tabId: string, constraintId: string) => void
-
- // Index operations
- addIndex: (tabId: string, index: IndexDefinition) => void
- updateIndex: (tabId: string, indexId: string, updates: Partial) => void
- removeIndex: (tabId: string, indexId: string) => void
-
- // Table properties
- updateTableProperties: (tabId: string, updates: Partial) => void
-
- // Diff tracking for edit mode
- getAlterTableBatch: (tabId: string) => AlterTableBatch | null
-
- // Validation
- validateDefinition: (tabId: string) => { valid: boolean; errors: string[] }
-
- // Cleanup
- clearTabState: (tabId: string) => void
-}
-
-interface TableDesignerState {
- original?: TableDefinition // For edit mode - track original state
- current: TableDefinition
- isDirty: boolean
- validationErrors: string[]
-}
-```
-
----
-
-## Phase 6: UI Components
-
-### New Components Structure:
-
-```
-src/renderer/src/components/
-├── table-designer/
-│ ├── table-designer.tsx # Main container
-│ ├── column-list.tsx # Column grid with drag-drop
-│ ├── column-editor-row.tsx # Inline column editing
-│ ├── column-editor-dialog.tsx # Full column editor modal
-│ ├── constraint-list.tsx # Constraint management
-│ ├── constraint-editor-dialog.tsx # Add/edit constraint
-│ ├── index-list.tsx # Index management
-│ ├── index-editor-dialog.tsx # Add/edit index
-│ ├── table-properties.tsx # Table-level settings
-│ ├── ddl-preview-panel.tsx # Live SQL preview
-│ ├── data-type-select.tsx # Type picker with search
-│ └── sequence-select.tsx # Sequence picker
-```
-
-### Main Component: `table-designer.tsx`
-
-Layout:
-```
-┌─────────────────────────────────────────────────────────────────┐
-│ Toolbar: [Save] [Preview SQL] [Cancel] | Table: schema.name │
-├─────────────────────────────────────────────────────────────────┤
-│ Tabs: [Columns] [Constraints] [Indexes] [Properties] │
-├─────────────────────────────────────────────────────────────────┤
-│ │
-│ ┌──────────────────────────────────────────────────────────┐ │
-│ │ Column Grid (primary view) │ │
-│ │ ┌─────┬──────────┬──────────┬────┬────┬────┬─────────┐ │ │
-│ │ │ ⋮⋮ │ Name │ Type │ PK │ NN │ UQ │ Default │ │ │
-│ │ ├─────┼──────────┼──────────┼────┼────┼────┼─────────┤ │ │
-│ │ │ ⋮⋮ │ id │ uuid │ ✓ │ ✓ │ │ gen_... │ │ │
-│ │ │ ⋮⋮ │ name │ varchar │ │ ✓ │ │ │ │ │
-│ │ │ ⋮⋮ │ email │ varchar │ │ ✓ │ ✓ │ │ │ │
-│ │ │ ⋮⋮ │ created │ timestamp│ │ ✓ │ │ now() │ │ │
-│ │ └─────┴──────────┴──────────┴────┴────┴────┴─────────┘ │ │
-│ │ [+ Add Column] │ │
-│ └──────────────────────────────────────────────────────────┘ │
-│ │
-│ ┌──────────────────────────────────────────────────────────┐ │
-│ │ DDL Preview (collapsible) │ │
-│ │ CREATE TABLE schema.table ( │ │
-│ │ id uuid PRIMARY KEY DEFAULT gen_random_uuid(), │ │
-│ │ ... │ │
-│ │ ); │ │
-│ └──────────────────────────────────────────────────────────┘ │
-└─────────────────────────────────────────────────────────────────┘
-```
-
-### Features by Tab:
-
-**Columns Tab:**
-- Drag-drop reordering
-- Inline editing for quick changes
-- Click to expand for advanced options
-- Visual indicators: PK (key icon), NOT NULL (*), UNIQUE (U)
-- Type suggestions as you type
-- Array type toggle
-- Collation selector for text types
-
-**Constraints Tab:**
-- List view with constraint type badges
-- Add constraint button with type selector
-- Foreign key builder with table/column pickers
-- Check constraint with SQL editor
-- Unique constraint with column multi-select
-
-**Indexes Tab:**
-- List of indexes with method badges
-- Column selector with order (ASC/DESC)
-- Partial index condition editor
-- INCLUDE column selector
-- CONCURRENT option toggle
-
-**Properties Tab:**
-- Table comment
-- Schema selector (for changing schema)
-- Tablespace selector
-- Partition configuration
-- Inheritance configuration
-- UNLOGGED toggle
-
----
-
-## Phase 7: Integration Points
-
-### Schema Explorer Updates
-
-Add to `schema-explorer.tsx`:
-
-1. "Create Table" button in schema header:
-```tsx
- createTableDesignerTab(connectionId, schema.name)}>
-
-
-```
-
-2. Context menu on tables:
-```tsx
-
- createTableDesignerTab(connectionId, schema.name, table.name)}>
- Edit Table Structure
-
- handleDropTable(schema.name, table.name)}>
- Drop Table...
-
-
-```
-
-### Tab Container Updates
-
-Add to `tab-container.tsx`:
-
-```tsx
-case 'table-designer':
- return
-```
-
----
-
-## Phase 8: Implementation Order
-
-### Step 1: Foundation (Day 1-2)
-1. Add all shared types to `packages/shared/src/index.ts`
-2. Create `ddl-builder.ts` with CREATE TABLE generation
-3. Add basic IPC handlers for create-table and preview-ddl
-
-### Step 2: Basic UI (Day 2-3)
-1. Create DDL store
-2. Add new tab type to tab-store
-3. Create basic TableDesigner component with column list
-4. Add column editing (inline + dialog)
-5. Add DDL preview panel
-
-### Step 3: Column Features (Day 3-4)
-1. Implement all column properties
-2. Add data type selector with all PostgreSQL types
-3. Add sequence picker for defaults
-4. Implement column validation
-
-### Step 4: Constraints (Day 4-5)
-1. Add constraint list UI
-2. Implement PRIMARY KEY constraint
-3. Implement FOREIGN KEY with table/column picker
-4. Implement UNIQUE and CHECK constraints
-
-### Step 5: Indexes (Day 5)
-1. Add index list UI
-2. Implement index creation with all options
-3. Add partial index support
-
-### Step 6: ALTER TABLE (Day 6-7)
-1. Implement `db:get-table-ddl` handler (reverse engineer table)
-2. Implement diff tracking in DDL store
-3. Generate ALTER TABLE statements
-4. Handle column type changes with USING
-
-### Step 7: Advanced Features (Day 7-8)
-1. Add partitioning support
-2. Add inheritance support
-3. Add custom type support
-4. Add schema explorer integration (create button, context menu)
-
-### Step 8: Polish (Day 8)
-1. Validation and error handling
-2. Keyboard shortcuts
-3. Undo/redo support
-4. Test with various edge cases
-
----
-
-## Keyboard Shortcuts
-
-| Shortcut | Action |
-|----------|--------|
-| `Cmd+S` | Save/Execute DDL |
-| `Cmd+Enter` | Preview SQL |
-| `Cmd+N` | Add new column |
-| `Delete` | Remove selected column |
-| `Cmd+Z` | Undo last change |
-| `Cmd+Shift+Z` | Redo |
-| `Tab` | Move to next column field |
-| `Shift+Tab` | Move to previous field |
-
----
-
-## Validation Rules
-
-1. **Table name**: Required, valid identifier, not reserved word
-2. **Column names**: Required, unique within table, valid identifier
-3. **Primary key**: At most one (can be composite)
-4. **Foreign keys**: Referenced table must exist, column types must match
-5. **Check constraints**: Valid SQL expression
-6. **Default values**: Type-compatible with column
-
----
-
-## Error Handling
-
-1. **Pre-execution validation**: Show errors inline before attempting execution
-2. **Execution errors**: Display PostgreSQL error message clearly
-3. **Partial success**: If ALTER TABLE fails mid-batch, show which operations succeeded
-4. **Recovery**: Provide option to rollback or continue
-
----
-
-## Testing Scenarios
-
-1. Create simple table with various column types
-2. Create table with composite primary key
-3. Create table with foreign keys to multiple tables
-4. Create table with CHECK constraints
-5. Create table with partial indexes
-6. Edit existing table - add column
-7. Edit existing table - change column type
-8. Edit existing table - add/remove constraints
-9. Drop table with cascade
-10. Create table with partitioning
diff --git a/docs/backend-plan.md b/docs/backend-plan.md
deleted file mode 100644
index f39c554..0000000
--- a/docs/backend-plan.md
+++ /dev/null
@@ -1,511 +0,0 @@
-# data-peek Backend & Business Plan
-
-> Planning document for the data-peek licensing system, payment integration, and marketing site.
-
----
-
-## Business Model
-
-### Pricing Strategy
-
-| Tier | Price | What's Included |
-|------|-------|-----------------|
-| **Pro License** | ~~$99~~ **$29** (Early Bird) | Perpetual license, 1 year of updates, 3 device activations |
-| **Free Tier** | $0 | Limited features (see below) |
-| **Cloud** (Future) | ~$5-8/month | Connection sync, saved queries, team features |
-
-### Early Bird Promotion
-- **Regular Price:** $99
-- **Launch Price:** $29 (Dec 2024 / Early Adopters)
-- **Messaging:** "70% off for early supporters"
-
-### Free vs Pro Features
-
-| Feature | Free | Pro ($29) |
-|---------|------|-----------|
-| Connections | 2 | Unlimited |
-| Query History | 50 queries | Unlimited |
-| Editor Tabs | 3 | Unlimited |
-| Export CSV/JSON | Yes | Yes |
-| ER Diagrams | 1 schema | Unlimited |
-| Inline Editing | View only | Full CRUD |
-| Query Execution Plans | No | Yes |
-| Updates | No | 1 year |
-| Device Activations | 1 | 3 |
-
----
-
-## Tech Stack
-
-| Component | Technology | Why |
-|-----------|------------|-----|
-| Marketing Site | Next.js 14 (App Router) | SSR, API routes, great DX |
-| Database | PostgreSQL (Supabase or Neon) | Familiar, reliable |
-| Auth | NextAuth.js | Easy OAuth + credentials |
-| Payments | DodoPayments | MoR, global reach, one-time + subscriptions |
-| Email | Resend | Developer-friendly, good deliverability |
-| Hosting | Vercel | Seamless Next.js deployment |
-| File Storage | Cloudflare R2 or S3 | App binary downloads |
-| Analytics | Plausible or PostHog | Privacy-friendly |
-
----
-
-## DodoPayments Integration
-
-### Why DodoPayments
-- Merchant of Record (handles taxes, VAT globally)
-- 150+ countries, 80+ currencies
-- One-time payments support (perfect for perpetual licenses)
-- SDKs for TypeScript/Node.js
-- Webhook support for automation
-
-### Product Setup in DodoPayments
-```
-Product: data-peek Pro License
-Type: One-time payment
-Price: $29 (promo) / $99 (regular)
-Metadata:
- - license_type: "pro"
- - updates_duration: "1_year"
- - max_activations: 3
-```
-
-### Webhook Events to Handle
-| Event | Action |
-|-------|--------|
-| `payment.completed` | Generate license key, store in DB, send email |
-| `payment.refunded` | Revoke license, update status |
-| `payment.failed` | Log for debugging, notify if needed |
-
----
-
-## Database Schema
-
-### Tables
-
-```sql
--- Customers (synced from DodoPayments)
-CREATE TABLE customers (
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
- email TEXT UNIQUE NOT NULL,
- name TEXT,
- dodo_customer_id TEXT UNIQUE,
- created_at TIMESTAMPTZ DEFAULT NOW(),
- updated_at TIMESTAMPTZ DEFAULT NOW()
-);
-
--- Licenses
-CREATE TABLE licenses (
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
- customer_id UUID REFERENCES customers(id),
- license_key TEXT UNIQUE NOT NULL,
- plan TEXT NOT NULL DEFAULT 'pro',
- status TEXT NOT NULL DEFAULT 'active', -- active, revoked, expired
- max_activations INT NOT NULL DEFAULT 3,
- dodo_payment_id TEXT UNIQUE,
- dodo_product_id TEXT,
- purchased_at TIMESTAMPTZ DEFAULT NOW(),
- updates_until TIMESTAMPTZ NOT NULL, -- purchased_at + 1 year
- created_at TIMESTAMPTZ DEFAULT NOW()
-);
-
--- Device Activations
-CREATE TABLE activations (
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
- license_id UUID REFERENCES licenses(id) ON DELETE CASCADE,
- device_id TEXT NOT NULL, -- Hardware fingerprint
- device_name TEXT, -- e.g., "MacBook Pro M2"
- os TEXT, -- macos, windows, linux
- app_version TEXT,
- activated_at TIMESTAMPTZ DEFAULT NOW(),
- last_validated_at TIMESTAMPTZ DEFAULT NOW(),
- is_active BOOLEAN DEFAULT TRUE,
- UNIQUE(license_id, device_id)
-);
-
--- App Releases (for update checks)
-CREATE TABLE releases (
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
- version TEXT UNIQUE NOT NULL, -- semver: 1.0.0
- release_notes TEXT,
- download_url_mac TEXT,
- download_url_mac_arm TEXT,
- download_url_windows TEXT,
- download_url_linux TEXT,
- is_latest BOOLEAN DEFAULT FALSE,
- min_supported_version TEXT, -- for forced updates
- released_at TIMESTAMPTZ DEFAULT NOW()
-);
-
--- Indexes
-CREATE INDEX idx_licenses_customer ON licenses(customer_id);
-CREATE INDEX idx_licenses_key ON licenses(license_key);
-CREATE INDEX idx_activations_license ON activations(license_id);
-CREATE INDEX idx_activations_device ON activations(device_id);
-```
-
----
-
-## API Endpoints
-
-### Public API (called by Electron app)
-
-```
-POST /api/license/validate
- Request: { licenseKey, deviceId }
- Response: { valid, plan, status, updatesUntil, activationsRemaining }
-
-POST /api/license/activate
- Request: { licenseKey, deviceId, deviceName, os, appVersion }
- Response: { success, activation, license }
-
-POST /api/license/deactivate
- Request: { licenseKey, deviceId }
- Response: { success, activationsRemaining }
-
-GET /api/updates/check?version=1.0.0&platform=macos
- Response: { hasUpdate, latestVersion, downloadUrl, releaseNotes, forceUpdate }
-```
-
-### Webhook Endpoint
-
-```
-POST /api/webhooks/dodo
- - Verify signature from DodoPayments
- - Handle payment.completed → create license
- - Handle payment.refunded → revoke license
-```
-
-### Protected API (requires auth, for account dashboard)
-
-```
-GET /api/account/licenses # List user's licenses
-GET /api/account/activations # List active devices
-POST /api/account/deactivate # Deactivate a device remotely
-GET /api/account/downloads # Get download links
-```
-
----
-
-## License Key Generation
-
-### Format
-```
-DPRO-XXXX-XXXX-XXXX-XXXX
-```
-- Prefix: `DPRO` (data-peek pro)
-- 4 groups of 4 alphanumeric characters
-- Total: 20 characters (easy to type, hard to guess)
-
-### Generation Logic
-```typescript
-import { randomBytes } from 'crypto'
-
-function generateLicenseKey(): string {
- const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' // No 0, O, 1, I (avoid confusion)
- const segments: string[] = []
-
- for (let i = 0; i < 4; i++) {
- let segment = ''
- for (let j = 0; j < 4; j++) {
- const randomIndex = randomBytes(1)[0] % chars.length
- segment += chars[randomIndex]
- }
- segments.push(segment)
- }
-
- return `DPRO-${segments.join('-')}`
-}
-```
-
----
-
-## Electron App Integration
-
-### License Activation Flow
-
-```
-┌─────────────────────────────────────────────────────────────────┐
-│ FIRST LAUNCH │
-├─────────────────────────────────────────────────────────────────┤
-│ │
-│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │
-│ │ Show │ │ User enters │ │ Call /activate │ │
-│ │ License │───▶│ license key │───▶│ API endpoint │ │
-│ │ Dialog │ │ │ │ │ │
-│ └─────────────┘ └──────────────┘ └────────┬────────┘ │
-│ │ │
-│ ┌────────────────────────┴──────┐ │
-│ ▼ ▼ │
-│ ┌─────────────┐ ┌───────────┐ │
-│ │ Valid │ │ Invalid │ │
-│ │ License │ │ Show │ │
-│ │ Store │ │ Error │ │
-│ │ locally │ │ │ │
-│ └─────────────┘ └───────────┘ │
-│ │
-└─────────────────────────────────────────────────────────────────┘
-```
-
-### Validation Strategy
-
-```typescript
-// On app startup
-async function checkLicense(): Promise {
- const stored = await getLicenseFromStore()
-
- if (!stored) {
- return { status: 'free', features: FREE_FEATURES }
- }
-
- // Try online validation
- try {
- const result = await validateOnline(stored.key, getDeviceId())
-
- if (result.valid) {
- // Update local cache
- await updateLicenseCache(result)
- return { status: 'pro', features: PRO_FEATURES, license: result }
- } else {
- // License revoked or invalid
- await clearLicenseStore()
- return { status: 'free', features: FREE_FEATURES, error: result.reason }
- }
- } catch (error) {
- // Offline - use cached validation (grace period)
- if (stored.cachedValidation && isWithinGracePeriod(stored.lastValidated)) {
- return { status: 'pro', features: PRO_FEATURES, offline: true }
- }
- return { status: 'free', features: FREE_FEATURES }
- }
-}
-```
-
-### Device Fingerprinting
-
-```typescript
-import { machineIdSync } from 'node-machine-id'
-import os from 'os'
-
-function getDeviceId(): string {
- return machineIdSync() // Unique per machine
-}
-
-function getDeviceName(): string {
- return os.hostname()
-}
-
-function getDeviceInfo() {
- return {
- deviceId: getDeviceId(),
- deviceName: getDeviceName(),
- os: process.platform, // darwin, win32, linux
- appVersion: app.getVersion()
- }
-}
-```
-
----
-
-## Marketing Site Structure
-
-### Pages
-
-```
-/ # Landing page
-/pricing # Pricing with buy button
-/download # Platform-specific downloads
-/docs # Getting started guide
-/docs/[slug] # Individual doc pages
-/faq # Frequently asked questions
-/changelog # Release history
-/blog # Updates, tutorials (future)
-/account # Dashboard (protected)
-/account/licenses # Manage licenses (protected)
-/account/downloads # Download links (protected)
-/login # Auth page
-```
-
-### Landing Page Sections
-
-1. **Hero** - Tagline, screenshot, CTA button
-2. **Problem** - Pain points with existing tools
-3. **Features** - Key capabilities with visuals
-4. **Demo** - GIF or video of the app in action
-5. **Comparison** - vs pgAdmin, DBeaver, TablePlus
-6. **Pricing** - Single tier, early bird callout
-7. **FAQ** - Common questions
-8. **CTA** - Final call to action
-
----
-
-## Email Templates
-
-### Welcome Email (after purchase)
-```
-Subject: Your data-peek Pro license 🎉
-
-Hi {name},
-
-Thank you for purchasing data-peek Pro!
-
-Your license key: {license_key}
-
-Quick start:
-1. Download data-peek: {download_link}
-2. Open the app and go to Settings → License
-3. Enter your license key
-
-Your license includes:
-✓ 1 year of updates (until {updates_until})
-✓ 3 device activations
-✓ All Pro features unlocked
-
-Need help? Reply to this email.
-
-Happy querying!
-— The data-peek team
-```
-
-### License Activation Email
-```
-Subject: data-peek activated on {device_name}
-
-Your license was just activated on a new device:
-
-Device: {device_name}
-Activated: {timestamp}
-Activations used: {used}/{max}
-
-Not you? Manage your devices at {dashboard_link}
-```
-
----
-
-## Implementation Roadmap
-
-### Phase 1: MVP (Week 1)
-- [ ] Set up Next.js project with App Router
-- [ ] Configure DodoPayments account and product
-- [ ] Create database schema (Supabase/Neon)
-- [ ] Implement `/api/webhooks/dodo` endpoint
-- [ ] Implement `/api/license/validate` endpoint
-- [ ] Implement `/api/license/activate` endpoint
-- [ ] Build landing page with pricing
-- [ ] Build download page
-- [ ] Deploy to Vercel
-- [ ] Test end-to-end purchase flow
-
-### Phase 2: Polish (Week 2)
-- [ ] Add account dashboard with NextAuth
-- [ ] Implement device management UI
-- [ ] Add email notifications (Resend)
-- [ ] Implement update checker API
-- [ ] Add analytics (Plausible)
-- [ ] Write FAQ page
-- [ ] Add basic docs/getting started
-
-### Phase 3: Electron Integration (Week 2-3)
-- [ ] Add license dialog to data-peek app
-- [ ] Implement device fingerprinting
-- [ ] Add license validation on startup
-- [ ] Implement feature gating (free vs pro)
-- [ ] Add "Check for updates" functionality
-- [ ] Handle offline grace period
-- [ ] Test activation/deactivation flow
-
-### Phase 4: Launch Prep (Week 3)
-- [ ] Create app store screenshots
-- [ ] Record demo video/GIF
-- [ ] Write launch blog post
-- [ ] Set up social media accounts
-- [ ] Prepare ProductHunt launch
-- [ ] Build releases for all platforms
-- [ ] Final QA testing
-
----
-
-## Security Considerations
-
-### API Security
-- [ ] Rate limiting on all endpoints (prevent brute force)
-- [ ] Webhook signature verification (DodoPayments)
-- [ ] Input validation on all parameters
-- [ ] SQL injection prevention (parameterized queries)
-
-### License Security
-- [ ] License keys stored hashed in DB? (or encrypted)
-- [ ] Device ID cannot be spoofed easily
-- [ ] Offline grace period limited (7-14 days)
-- [ ] Anomaly detection (too many activations)
-
-### Data Privacy
-- [ ] Minimal data collection
-- [ ] No tracking in the app
-- [ ] Clear privacy policy
-- [ ] GDPR compliance (if EU customers)
-
----
-
-## Metrics to Track
-
-### Business Metrics
-- Total licenses sold
-- Revenue (MRR if cloud tier added)
-- Conversion rate (free → pro)
-- Refund rate
-
-### Product Metrics
-- Daily/weekly active users
-- Feature usage (which features are popular)
-- Error rates
-- Update adoption rate
-
-### Marketing Metrics
-- Website visitors
-- Download counts
-- Trial starts
-- Email open/click rates
-
----
-
-## Future Considerations
-
-### Cloud Tier (v2)
-- User accounts required
-- Connection sync across devices
-- Saved queries library
-- Team sharing features
-- Subscription billing via DodoPayments
-
-### Additional Payment Options
-- Regional pricing
-- Team/volume licenses
-- Educational discounts
-- Lifetime deals (AppSumo?)
-
----
-
-## Open Questions
-
-- [ ] Exact DodoPayments webhook event names (check their docs)
-- [ ] License key format preference
-- [ ] Offline grace period duration (7 or 14 days?)
-- [ ] Domain name for marketing site
-- [ ] App signing certificates (macOS notarization, Windows signing)
-
----
-
-## Resources
-
-- [DodoPayments Docs](https://docs.dodopayments.com)
-- [Next.js App Router](https://nextjs.org/docs/app)
-- [NextAuth.js](https://next-auth.js.org/)
-- [Resend](https://resend.com/docs)
-- [Supabase](https://supabase.com/docs)
-- [node-machine-id](https://www.npmjs.com/package/node-machine-id)
-
----
-
-*Document created: November 2024*
-*Last updated: November 2024*
diff --git a/docs/features.md b/docs/features.md
deleted file mode 100644
index f170097..0000000
--- a/docs/features.md
+++ /dev/null
@@ -1,279 +0,0 @@
-# data-peek Feature Overview
-
-> A minimal, fast, beautiful PostgreSQL client for developers who want to quickly peek at their data.
-
----
-
-## Product Summary
-
-**data-peek** is a lightweight desktop database client designed for developers who need quick, frictionless access to their PostgreSQL databases. Unlike bloated alternatives like pgAdmin or DBeaver, data-peek focuses on speed, simplicity, and a keyboard-first experience.
-
-**Target Audience:** Developers, data engineers, backend engineers, and anyone who needs to quickly query and explore PostgreSQL databases without the overhead of enterprise tools.
-
-**Platforms:** macOS (Apple Silicon + Intel), Windows, Linux
-
----
-
-## Key Value Propositions
-
-| Benefit | Description |
-|---------|-------------|
-| **Lightning Fast** | Opens in under 2 seconds. No splash screens, no waiting. |
-| **Zero Configuration** | Connect and query immediately. No complex setup required. |
-| **Keyboard-First** | Power users can do everything without touching the mouse. |
-| **Beautiful & Modern** | Dark and light themes with a clean, distraction-free UI. |
-| **Privacy-First** | No telemetry, no tracking. Your data stays on your machine. |
-| **Secure** | Connection credentials are encrypted locally. |
-| **Pay Once, Own Forever** | No subscriptions. One-time purchase with 1 year of updates. |
-
----
-
-## Pricing
-
-### Free Tier
-Get started at no cost:
-- 2 database connections
-- 50 query history items
-- 3 editor tabs
-- 1 schema for ER diagrams
-- CSV/JSON export
-
-### Pro License — ~~$99~~ $29 (Early Bird)
-Unlock everything:
-- **Unlimited** connections
-- **Unlimited** query history
-- **Unlimited** tabs
-- **Unlimited** ER diagrams
-- Inline data editing (INSERT/UPDATE/DELETE)
-- Query execution plans (EXPLAIN/ANALYZE)
-- 3 device activations
-- 1 year of updates
-- **Pay once, use forever**
-
-### Cloud (Coming Soon)
-For power users and teams:
-- Everything in Pro
-- Sync connections across devices
-- Cloud-saved queries
-- Team sharing
-- ~$5-8/month
-
----
-
-## Feature List
-
-### Connection Management
-
-| Feature | Description |
-|---------|-------------|
-| **Quick Connection Setup** | Add connections with host, port, database, user, and password — or paste a connection string |
-| **Connection String Parsing** | Paste any PostgreSQL connection URL and auto-fill all fields |
-| **Test Before Save** | Verify connections work before adding them |
-| **Encrypted Storage** | Credentials stored securely with encryption |
-| **SSL Support** | Connect to SSL-enabled databases |
-| **Connection Switcher** | Quickly switch between multiple database connections |
-| **Edit & Delete** | Manage saved connections with ease |
-
-### Query Editor
-
-| Feature | Description |
-|---------|-------------|
-| **Monaco Editor** | Same editor engine that powers VS Code |
-| **SQL Syntax Highlighting** | Full SQL syntax highlighting with PostgreSQL support |
-| **Smart Autocomplete** | Schema-aware suggestions for tables, columns, and SQL keywords |
-| **Multi-Tab Support** | Work on multiple queries simultaneously with independent tabs |
-| **Query Formatting** | Auto-format SQL with `Cmd/Ctrl + Shift + F` |
-| **Run Query** | Execute with `Cmd/Ctrl + Enter` |
-| **Collapsible Editor** | Minimize the editor to focus on results |
-
-### Results Viewer
-
-| Feature | Description |
-|---------|-------------|
-| **Data Table View** | View results in a clean, sortable table |
-| **Data Type Indicators** | Color-coded badges showing column types |
-| **Query Metrics** | See row count and query execution time |
-| **Pagination** | Navigate large result sets with customizable page sizes |
-| **Copy Cell** | Click any cell to copy its value |
-| **Copy Row as JSON** | Export individual rows as JSON objects |
-| **Export to CSV** | Download results as CSV files |
-| **Export to JSON** | Download results as JSON files |
-| **NULL Styling** | Clear visual distinction for NULL values |
-| **Foreign Key Navigation** | Click FK cells to view related records |
-| **JSON/JSONB Viewer** | Expand and inspect JSON columns inline |
-
-### Schema Explorer
-
-| Feature | Description |
-|---------|-------------|
-| **Tree View Navigation** | Browse schemas, tables, and views hierarchically |
-| **Column Details** | See column names, data types, and constraints |
-| **Primary Key Indicators** | Visual markers for primary key columns |
-| **Nullable Indicators** | See which columns allow NULL values |
-| **Foreign Key Display** | View foreign key relationships |
-| **Table Search** | Filter tables by name with instant search |
-| **Click to Query** | Click any table to generate a SELECT query |
-| **Schema Refresh** | Reload schema after database changes |
-
-### Query History
-
-| Feature | Description |
-|---------|-------------|
-| **Auto-Save** | Every executed query is automatically saved |
-| **Persistent Storage** | History survives app restarts |
-| **Query Metadata** | See execution time, row count, and status for each query |
-| **Quick Load** | Click any history item to load it into the editor |
-| **Copy to Clipboard** | Copy previous queries without loading |
-| **Clear History** | Remove all or individual history items |
-| **Query Type Badges** | Visual indicators for SELECT, INSERT, UPDATE, DELETE |
-| **Relative Timestamps** | "5 minutes ago", "yesterday", etc. |
-
-### Inline Data Editing
-
-| Feature | Description |
-|---------|-------------|
-| **Edit Cells** | Double-click to modify cell values directly |
-| **Add Rows** | Insert new records with a visual form |
-| **Delete Rows** | Remove records with confirmation |
-| **SQL Preview** | Review generated SQL before executing changes |
-| **Batch Operations** | Queue multiple changes before committing |
-| **Discard Changes** | Undo pending edits before saving |
-| **Type-Safe Editing** | Input validation based on column data types |
-
-### ER Diagram Visualization
-
-| Feature | Description |
-|---------|-------------|
-| **Visual Schema Map** | See your database structure as an interactive diagram |
-| **Table Nodes** | Each table displays all columns with types |
-| **Relationship Lines** | Foreign key connections visualized as links |
-| **Primary Key Highlights** | Yellow indicators for PK columns |
-| **Foreign Key Highlights** | Blue indicators for FK columns |
-| **Pan & Zoom** | Navigate large schemas with ease |
-| **Mini Map** | Overview navigation for complex databases |
-
-### Query Execution Plans
-
-| Feature | Description |
-|---------|-------------|
-| **EXPLAIN Visualization** | See query execution plans in a visual tree |
-| **Node Type Coloring** | Color-coded operations (scans, joins, sorts) |
-| **Cost Analysis** | View estimated vs actual costs |
-| **Performance Metrics** | Execution time breakdown by operation |
-| **Buffer Statistics** | I/O and memory usage details |
-| **Expandable Nodes** | Drill into plan details |
-
-### User Interface
-
-| Feature | Description |
-|---------|-------------|
-| **Dark Mode** | Easy on the eyes for long coding sessions |
-| **Light Mode** | Clean, bright interface when you prefer it |
-| **System Preference** | Automatically match your OS theme |
-| **Resizable Panels** | Drag to resize sidebar and editor |
-| **Collapsible Sidebar** | Maximize workspace when needed |
-| **Loading States** | Clear feedback during operations |
-| **Error Handling** | Helpful error messages with details |
-| **Empty States** | Guided prompts when there's no data |
-
-### Keyboard Shortcuts
-
-| Shortcut | Action |
-|----------|--------|
-| `Cmd/Ctrl + Enter` | Execute query |
-| `Cmd/Ctrl + Shift + F` | Format SQL |
-| `Cmd/Ctrl + P` | Open connection picker |
-| `Cmd/Ctrl + S` | Save query to file |
-| `Cmd/Ctrl + O` | Open query from file |
-| `Cmd/Ctrl + Shift + 1-9` | Switch between connections |
-
----
-
-## Technical Highlights
-
-| Aspect | Details |
-|--------|---------|
-| **Framework** | Electron with React 19 |
-| **Editor** | Monaco (VS Code engine) |
-| **Database Driver** | Native PostgreSQL (pg) |
-| **Local Storage** | SQLite for history and settings |
-| **Security** | Encrypted credential storage |
-| **Build Targets** | macOS DMG, Windows exe/msi, Linux AppImage |
-
----
-
-## What data-peek is NOT
-
-To set clear expectations:
-
-- **Not a database admin tool** — Focus is on querying and exploring, not server management
-- **Not a data migration tool** — No import/export of entire databases
-- **Not multi-database** — PostgreSQL only (MySQL/SQLite coming in future versions)
-- **Not enterprise software** — Built for individual developers (team features coming with Cloud tier)
-
----
-
-## Comparison with Alternatives
-
-| Feature | data-peek | pgAdmin | DBeaver | TablePlus |
-|---------|-----------|---------|---------|-----------|
-| Startup Time | < 2s | 5-10s | 10-15s | 2-3s |
-| Memory Usage | Low | High | Very High | Low |
-| Learning Curve | Minimal | Steep | Steep | Minimal |
-| Price | Free + $29 Pro | Free | Free/Paid | $69 |
-| PostgreSQL Focus | Yes | Yes | No | No |
-| ER Diagrams | Yes | Yes | Yes | Yes |
-| Inline Editing | Yes | Yes | Yes | Yes |
-| Query Plans | Yes | Yes | Yes | Limited |
-| Modern UI | Yes | No | No | Yes |
-
----
-
-## Coming Soon
-
-Features planned for future releases:
-
-- MySQL and SQLite support
-- SSH tunnel connections
-- Saved queries / snippets library
-- Query cancellation
-- CSV data import
-- Connection groups/folders
-- **Cloud Sync** — Sync connections and saved queries across devices
-- **Team Features** — Share queries and connections with your team
-
----
-
-## Screenshots
-
-*[Add screenshots here]*
-
-- Connection dialog
-- Query editor with results
-- Schema explorer tree
-- ER diagram view
-- Query execution plan
-- Inline data editing
-- Dark/Light theme comparison
-
----
-
-## One-Liner Descriptions
-
-For various marketing contexts:
-
-**Tagline:**
-> Peek at your data. Fast.
-
-**Short (10 words):**
-> A fast, beautiful PostgreSQL client for developers who value simplicity.
-
-**Medium (25 words):**
-> data-peek is a lightweight PostgreSQL desktop client with a modern UI, keyboard shortcuts, and features like ER diagrams and query plans — without the bloat.
-
-**Long (50 words):**
-> data-peek is the PostgreSQL client developers actually want to use. Lightning-fast startup, Monaco-powered SQL editor, visual ER diagrams, query execution plans, inline data editing, and a beautiful dark/light UI. No telemetry, no subscriptions, no bloat. Pay once, own forever. Available for macOS, Windows, and Linux.
-
----
-
-*Document generated: November 2025*
diff --git a/docs/future-plan.md b/docs/future-plan.md
deleted file mode 100644
index 513f934..0000000
--- a/docs/future-plan.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Future Plan
-
-## Quick Wins
-- [x] Query history - browse and re-run previous queries
-- [x] Export results to CSV/JSON
-- [x] Table search - quickly find tables in large schemas
-- [x] Dark/light theme toggle (already in settings)
-- [x] Connection picker (Cmd+P) and quick switching (Cmd+Shift+1-9)
-
-## Medium Effort
-- [ ] Saved queries/snippets - bookmark frequently used queries
-- [ ] Column statistics - show min/max/null counts/distinct values
-- [x] Connection folders/groups - organize many connections
-- [ ] Multi-statement query execution (run multiple queries separated by `;`)
-
-## Bigger Features
-- [x] ERD visualization - see table relationships visually
-- [x] Query execution plan viewer - analyze query performance (EXPLAIN ANALYZE)
-- [ ] Data visualization - charts from query results
-- [x] SQL autocomplete improvements (table/column suggestions) - already implemented
diff --git a/docs/release-guide.md b/docs/release-guide.md
deleted file mode 100644
index 9cb1a2c..0000000
--- a/docs/release-guide.md
+++ /dev/null
@@ -1,329 +0,0 @@
-# data-peek Release Guide
-
-This document covers everything needed to ship data-peek for macOS, Windows, and Linux.
-
----
-
-## TL;DR — Can I Ship for Free?
-
-**Yes.** Here's the reality:
-
-| Platform | Free Option | Paid Option | User Experience Difference |
-|----------|-------------|-------------|---------------------------|
-| **Linux** | ✅ No signing needed | N/A | No difference |
-| **macOS** | ✅ Ad-hoc signing | $99/year Apple Developer | Warning dialog vs no warning |
-| **Windows** | ✅ Unsigned | ~$200-400/year certificate | SmartScreen warning vs trusted |
-
-Most open-source Electron apps ship unsigned. Users can bypass warnings.
-
----
-
-## Platform-Specific Details
-
-### Linux — No Signing Required ✅
-
-Linux doesn't require code signing. Your current setup is ready:
-- AppImage: Works out of the box
-- Snap: Works out of the box
-- Deb: Works out of the box
-
-**Action needed:** None. Just build and distribute.
-
----
-
-### macOS — Options
-
-#### Option 1: Unsigned/Ad-hoc (Free) ✅
-
-Users will see: *"data-peek can't be opened because Apple cannot check it for malicious software"*
-
-**Workaround for users:**
-1. Right-click the app → Open (first time only)
-2. Or: `xattrs -cr /Applications/data-peek.app`
-
-**Pros:** Free, works fine for developer tools
-**Cons:** Scary warning, extra step for users
-
-**Current config already supports this** — just build and distribute.
-
-#### Option 2: Apple Developer Program ($99/year)
-
-Users will see: No warning, app opens normally.
-
-**What you get:**
-- Developer ID certificate for signing
-- Notarization (Apple scans your app)
-- No Gatekeeper warnings
-
-**When to consider:** If you want a polished user experience or plan to distribute via Mac App Store.
-
----
-
-### Windows — Options
-
-#### Option 1: Unsigned (Free) ✅
-
-Users will see: *"Windows protected your PC — Microsoft Defender SmartScreen prevented an unrecognized app from starting"*
-
-**Workaround for users:**
-1. Click "More info"
-2. Click "Run anyway"
-
-**Pros:** Free
-**Cons:** SmartScreen warning scares users, some corporate machines block unsigned apps
-
-**Note:** SmartScreen builds reputation over time. After enough users download and run your app without issues, warnings may reduce.
-
-#### Option 2: Code Signing Certificate ($200-600/year)
-
-Traditional EV (Extended Validation) certificates from:
-- DigiCert (~$400-600/year)
-- Sectigo (~$200-400/year)
-- SSL.com (~$200/year)
-
-**Pros:** Immediate SmartScreen trust (EV certs), professional appearance
-**Cons:** Expensive, annual renewal
-
-#### Option 3: Azure Trusted Signing (~$10/month) 💡
-
-Microsoft's newer, cheaper alternative:
-- Pay-as-you-go pricing
-- Works with electron-builder
-- Builds SmartScreen reputation faster than unsigned
-
-**Pros:** Cheap, modern, Microsoft-backed
-**Cons:** Requires Azure account, slightly more setup
-
-#### Option 4: SignPath (Free for Open Source) 💡
-
-[SignPath.io](https://signpath.io) offers free code signing for open-source projects.
-
-**Requirements:**
-- Public GitHub repository
-- OSS license (MIT qualifies)
-- Apply and get approved
-
-**Pros:** Completely free
-**Cons:** Approval process, builds must go through their CI
-
----
-
-## Recommended Approach
-
-### For Initial Release (v1.0)
-
-Ship unsigned on all platforms:
-
-1. **Linux** — No changes needed
-2. **macOS** — Users right-click → Open (one time)
-3. **Windows** — Users click "More info" → "Run anyway"
-
-Include clear installation instructions in README.
-
-### For Future Releases
-
-Consider signing when:
-- You have paying users (Pro tier)
-- Download volume justifies the cost
-- Corporate users need signed apps
-
----
-
-## Release Checklist
-
-### Pre-Release
-
-- [ ] Update `electron-builder.yml`:
- - [ ] Change `appId` to `com.datapeek.app`
- - [ ] Remove `electronDownload.mirror` line
- - [ ] Update `publish` config (see below)
-- [ ] Update `package.json`:
- - [ ] Set proper `author`
- - [ ] Set `homepage` to GitHub repo
-- [ ] Add LICENSE file (MIT)
-- [ ] Add README with screenshots and install instructions
-- [ ] Test builds on each platform
-
-### electron-builder.yml Updates
-
-```yaml
-appId: com.datapeek.app
-productName: data-peek
-
-# ... keep existing config ...
-
-# For GitHub Releases (recommended)
-publish:
- provider: github
- owner: Rohithgilla12
- repo: data-peek
-
-# Remove this line:
-# electronDownload:
-# mirror: https://npmmirror.com/mirrors/electron/
-```
-
-### Building Releases
-
-```bash
-# From apps/desktop directory
-
-# macOS (builds for current architecture)
-pnpm build:mac
-
-# macOS universal (Intel + Apple Silicon)
-# Add to electron-builder.yml under mac:
-# target:
-# - target: dmg
-# arch: [x64, arm64]
-
-# Windows
-pnpm build:win
-
-# Linux
-pnpm build:linux
-```
-
-### Creating a GitHub Release
-
-1. Tag your release:
- ```bash
- git tag v1.0.0
- git push origin v1.0.0
- ```
-
-2. Go to GitHub → Releases → Draft new release
-
-3. Upload build artifacts:
- - `data-peek-desktop-1.0.0.dmg` (macOS)
- - `data-peek-desktop-1.0.0-setup.exe` (Windows)
- - `data-peek-desktop-1.0.0.AppImage` (Linux)
- - `data-peek-desktop-1.0.0.snap` (Linux)
- - `data-peek-desktop-1.0.0.deb` (Linux)
-
-4. Write release notes and publish
-
----
-
-## CI/CD (Optional but Recommended)
-
-Automate builds with GitHub Actions. Create `.github/workflows/release.yml`:
-
-```yaml
-name: Release
-
-on:
- push:
- tags:
- - 'v*'
-
-jobs:
- build:
- strategy:
- matrix:
- os: [macos-latest, ubuntu-latest, windows-latest]
-
- runs-on: ${{ matrix.os }}
-
- steps:
- - uses: actions/checkout@v4
-
- - uses: pnpm/action-setup@v2
- with:
- version: 8
-
- - uses: actions/setup-node@v4
- with:
- node-version: 20
- cache: 'pnpm'
-
- - run: pnpm install
-
- - name: Build
- run: pnpm --filter @data-peek/desktop build
-
- - name: Build Electron app
- run: |
- cd apps/desktop
- pnpm exec electron-builder --publish never
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Upload artifacts
- uses: actions/upload-artifact@v4
- with:
- name: dist-${{ matrix.os }}
- path: apps/desktop/dist/*.{dmg,exe,AppImage,snap,deb}
-```
-
----
-
-## Installation Instructions for Users
-
-Include this in your README:
-
-### macOS
-
-1. Download `data-peek-desktop-x.x.x.dmg`
-2. Open the DMG and drag to Applications
-3. **First launch:** Right-click the app → Click "Open" → Click "Open" again
-
- (This is required because the app is not notarized)
-
-### Windows
-
-1. Download `data-peek-desktop-x.x.x-setup.exe`
-2. Run the installer
-3. **If you see SmartScreen warning:** Click "More info" → "Run anyway"
-
-### Linux
-
-**AppImage:**
-```bash
-chmod +x data-peek-desktop-x.x.x.AppImage
-./data-peek-desktop-x.x.x.AppImage
-```
-
-**Snap:**
-```bash
-sudo snap install data-peek-desktop-x.x.x.snap --dangerous
-```
-
-**Deb:**
-```bash
-sudo dpkg -i data-peek-desktop-x.x.x.deb
-```
-
----
-
-## Cost Summary
-
-| Approach | Cost | Notes |
-|----------|------|-------|
-| Ship unsigned | $0 | Users see warnings |
-| macOS only signing | $99/year | Apple Developer Program |
-| Windows only signing | $10-400/year | Azure TS or traditional cert |
-| Both platforms signed | $109-500/year | Combined |
-| SignPath (Windows) | $0 | Free for OSS, requires approval |
-
----
-
-## Future Considerations
-
-### Auto-Updates
-
-Current config uses `electron-updater`. For unsigned apps:
-- macOS: Auto-updates work but user must approve
-- Windows: Auto-updates work
-- Linux: AppImage supports auto-updates via `electron-updater`
-
-### Mac App Store
-
-Requires Apple Developer Program + additional review process. Consider only if:
-- You want discoverability
-- You're okay with Apple's 15-30% cut
-- Your app meets their guidelines
-
-### Windows Store
-
-Possible but requires Microsoft Partner account. Similar considerations to Mac App Store.
diff --git a/docs/scope.md b/docs/scope.md
deleted file mode 100644
index 4a3dfe9..0000000
--- a/docs/scope.md
+++ /dev/null
@@ -1,333 +0,0 @@
-# data-peek v1.0 Scope Document
-
-> A minimal, fast, beautiful Postgres client for developers who want to quickly peek at their data.
-
-## Target User
-
-Developers who need a lightweight alternative to pgAdmin/DBeaver for day-to-day queries.
-
-## Core Principles
-
-- **Simple over feature-rich** — Do less, but do it well
-- **Fast to open, fast to query** — No bloat
-- **Keyboard-first** — Power users shouldn't need a mouse
-
----
-
-## Tech Stack
-
-| Layer | Choice | Why |
-|-------|--------|-----|
-| Desktop | Electron | Community, TS-native, contributor-friendly |
-| Frontend | React + TypeScript | Industry standard, type safety |
-| Bundler | electron-vite | Fast, modern, great DX |
-| UI | shadcn/ui + Tailwind | Beautiful, accessible, customizable |
-| State | Zustand | Simple, minimal boilerplate |
-| Query Editor | Monaco | VS Code engine, excellent SQL support |
-| Local Storage | SQLite (better-sqlite3) | Query history, cached schemas |
-| Config | electron-store | Encrypted connection credentials |
-| Database Client | pg | Native Postgres driver |
-
----
-
-## In Scope (v1.0)
-
-### Connection Management
-
-- [x] Add new Postgres connection (host, port, database, user, password)
-- [x] Edit existing connection
-- [x] Delete connection
-- [x] Test connection before saving
-- [x] Encrypted credential storage (electron-store)
-- [x] Connection list in sidebar
-- [x] SSL connection support (basic)
-
-### Query Editor
-
-- [x] Monaco editor with SQL syntax highlighting
-- [x] Single query tab (multi-tab is v1.1) — *Actually implemented multi-tab!*
-- [x] Run query: `Cmd/Ctrl + Enter`
-- [ ] Clear editor: `Cmd/Ctrl + L`
-- [x] Basic error display with message
-
-### Results Viewer
-
-- [x] Table view with columns and rows
-- [x] Column headers with data type indicators
-- [x] Row count and query duration display
-- [x] Client-side pagination (100 rows per page)
-- [x] Copy cell value on click
-- [x] Copy row as JSON
-- [x] Export results to CSV
-- [x] Export results to JSON
-- [x] NULL value indicator styling
-
-### Schema Explorer
-
-- [x] Tree view: Connection → Schemas → Tables/Views
-- [x] Show columns under each table:
- - Column name
- - Data type
- - Nullable indicator
- - Primary key indicator
-- [x] Click table name to insert into editor
-- [x] Refresh schema button
-- [x] Collapse/expand nodes
-
-### Query History
-
-- [x] Auto-save last 100 executed queries (local SQLite)
-- [x] Store: query text, timestamp, duration, row count
-- [x] Display in sidebar panel
-- [x] Click to load query into editor
-- [x] Clear history option
-- [x] Persist across sessions
-
-### UI/UX
-
-- [x] Dark mode only (light mode is v1.1) — *Actually implemented light mode + system preference!*
-- [x] Resizable sidebar (drag handle)
-- [x] Loading states for queries
-- [x] Empty states with helpful messages
-- [x] Error states with clear messaging
-- [x] Keyboard shortcuts:
- - `Cmd/Ctrl + Enter` — Run query
- - `Cmd/Ctrl + S` — Save query to file
- - `Cmd/Ctrl + O` — Open query from file
- - `Cmd/Ctrl + ,` — Open settings
-
-### Platform Support
-
-- [x] macOS build (DMG, Apple Silicon + Intel)
-- [x] Linux build (AppImage)
-- [x] Windows build (exe/msi)
-
----
-
-## Out of Scope (v1.0)
-
-These features are explicitly deferred to future versions. When tempted to add them, resist.
-
-| Feature | Target Version | Status |
-|---------|----------------|--------|
-| Multiple query tabs | v1.1 | ✅ Done |
-| MySQL adapter | v1.1 | |
-| SQLite adapter | v1.1 | |
-| Light theme | v1.1 | ✅ Done |
-| Connection groups/folders | v1.1 | |
-| Autocomplete (tables/columns) | v1.2 | ✅ Done (schema-aware) |
-| Query formatting/beautify | v1.2 | ✅ Done |
-| Saved queries / snippets library | v1.2 | |
-| SSH tunnel connections | v1.2 | |
-| Query cancellation | v1.2 | |
-| Table data editing (inline UPDATE/INSERT) | v2.0 | ✅ Done |
-| ER diagram visualization | v2.0 | ✅ Done |
-| Query EXPLAIN/ANALYZE visualizer | v2.0 | ✅ Done |
-| Import data from CSV | v2.0 | |
-| Database diff tool | v2.0 | |
-| Cloud sync (connections, history) | Pro | |
-| Team workspaces | Pro | |
-| Shared query library | Pro | |
-| SSO / SAML | Pro | |
-| Audit logs | Pro | |
-
----
-
-## Technical Boundaries
-
-- **No ORM** — Raw `pg` client only, keep it simple
-- **No server component** — Pure desktop app, no backend
-- **No auth in v1** — Local app, no user accounts
-- **No auto-updates in v1** — Manual download for updates
-- **No telemetry** — Privacy first, no tracking
-
----
-
-## Architecture Overview
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ Renderer Process (React) │
-│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐│
-│ │ Sidebar │ │ Query Editor│ │ Results Viewer ││
-│ │ - Conns │ │ (Monaco) │ │ - Table/JSON/Export ││
-│ │ - Schema │ │ │ │ ││
-│ │ - History │ │ │ │ ││
-│ └─────────────┘ └─────────────┘ └─────────────────────────┘│
-│ │ │
-│ ┌───────▼───────┐ │
-│ │ IPC Bridge │ │
-│ └───────┬───────┘ │
-└────────────────────────────┼────────────────────────────────┘
- │
-┌────────────────────────────┼────────────────────────────────┐
-│ Main Process (Node.js) │
-│ ┌───────▼───────┐ │
-│ │ Service Layer │ │
-│ └───────┬───────┘ │
-│ ┌───────────────────┼───────────────────┐ │
-│ ▼ ▼ ▼ │
-│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
-│ │Connection│ │ Query │ │ Schema │ │
-│ │ Manager │ │ Engine │ │ Explorer │ │
-│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
-│ └──────────────────┼───────────────────┘ │
-│ ┌─────▼─────┐ │
-│ │ Postgres │ │
-│ │ Adapter │ │
-│ └───────────┘ │
-└─────────────────────────────────────────────────────────────┘
-```
-
----
-
-## UI Layout
-
-```
-┌──────────────────────────────────────────────────────────────────┐
-│ data-peek [Connection: prod-db ▼] [⚙️] │
-├────────────────┬─────────────────────────────────────────────────┤
-│ │ │
-│ CONNECTIONS │ SELECT * FROM users │
-│ ├─ prod-db ● │ WHERE created_at > '2024-01-01' │
-│ ├─ staging │ LIMIT 100; │
-│ └─ local │ │
-│ │ [▶ Run] │
-│ SCHEMA ├─────────────────────────────────────────────────┤
-│ ▼ public │ │
-│ ├─ users │ id │ name │ email │ created_at │
-│ ├─ orders │ ───┼─────────┼─────────────────┼────────────── │
-│ └─ products │ 1 │ Alice │ alice@test.com │ 2024-01-15 │
-│ │ 2 │ Bob │ bob@test.com │ 2024-02-20 │
-│ HISTORY │ 3 │ Carol │ carol@test.com │ 2024-03-10 │
-│ ├─ SELECT ... │ ... │
-│ ├─ UPDATE ... ├─────────────────────────────────────────────────┤
-│ └─ ... │ ✓ 100 rows │ 24ms │ Page 1/10 │ [CSV] [JSON] │
-└────────────────┴─────────────────────────────────────────────────┘
-```
-
----
-
-## Milestones
-
-### M1: Foundation
-- [x] Electron app scaffolded with electron-vite
-- [x] Monorepo structure with pnpm workspaces
-- [x] Can connect to a Postgres database
-- [x] Can run a hardcoded query and log results
-
-### M2: Connection Management
-- [x] Connection form UI (add/edit)
-- [x] Connection list in sidebar
-- [x] Test connection functionality
-- [x] Encrypted storage with electron-store
-- [x] Delete connection
-
-### M3: Schema Explorer
-- [x] Fetch and display schemas
-- [x] Fetch and display tables per schema
-- [x] Fetch and display columns per table
-- [x] Tree view component with expand/collapse
-- [x] Click to insert table name
-
-### M4: Query Editor
-- [x] Monaco editor integration
-- [x] SQL syntax highlighting
-- [x] Run query button
-- [x] Keyboard shortcut (Cmd+Enter)
-- [x] Error display
-
-### M5: Results Viewer
-- [x] Table component for results
-- [x] Column headers
-- [x] Pagination
-- [x] Copy cell/row
-- [x] Export to CSV
-- [x] Export to JSON
-
-### M6: Query History
-- [x] SQLite setup for local storage
-- [x] Auto-save executed queries
-- [x] History list in sidebar
-- [x] Click to load into editor
-- [x] Clear history
-
-### M7: Polish & Release
-- [x] Keyboard shortcuts complete
-- [x] Loading states
-- [x] Error handling
-- [x] Empty states
-- [x] Build for macOS
-- [x] Build for Linux
-- [x] Build for Windows
-- [ ] README with screenshots
-- [ ] v1.0 release
-
----
-
-## Success Criteria
-
-v1.0 is complete when:
-
-1. ✅ Can connect to a Postgres database
-2. ✅ Can browse schema (schemas, tables, columns)
-3. ✅ Can write and run SQL queries
-4. ✅ Can view results in a table
-5. ✅ Can export results to CSV/JSON
-6. ✅ Query history persists across sessions
-7. ✅ App opens in under 2 seconds
-8. ✅ Feels snappy — no UI lag
-9. ✅ Builds available for macOS, Linux, Windows
-
----
-
-## Non-Goals
-
-To keep scope tight, these are explicitly NOT goals for v1:
-
-- Being a full database administration tool
-- Competing with DataGrip/TablePlus on features
-- Supporting every Postgres feature
-- Having a plugin system
-- Mobile support
-
----
-
-## Open Source Strategy
-
-### License
-MIT — Maximum adoption, contributor-friendly.
-
-### Contribution Guidelines
-- PRs welcome for bug fixes and v1 scope items
-- Features outside v1 scope will be reviewed for v1.1+
-- All PRs require tests for new functionality
-
-### Future Monetization (Post v1)
-Open core model:
-- Free: Everything in v1 scope, forever
-- Pro: Cloud sync, team features, priority support
-
----
-
-## Resources
-
-- [Electron Documentation](https://www.electronjs.org/docs)
-- [electron-vite](https://electron-vite.org/)
-- [Monaco Editor React](https://github.com/suren-atoyan/monaco-react)
-- [shadcn/ui](https://ui.shadcn.com/)
-- [Zustand](https://github.com/pmndrs/zustand)
-- [node-postgres (pg)](https://node-postgres.com/)
-
----
-
-## Changelog
-
-| Date | Change |
-|------|--------|
-| 2024-XX-XX | Initial scope document created |
-| 2025-11-28 | Updated implementation status - v1.0 scope complete + bonus v2.0 features |
-
----
-
-*Remember: When in doubt, leave it out. Ship v1, then iterate.*
\ No newline at end of file
diff --git a/docs/web-integration-guide.md b/docs/web-integration-guide.md
deleted file mode 100644
index 479c083..0000000
--- a/docs/web-integration-guide.md
+++ /dev/null
@@ -1,831 +0,0 @@
-# data-peek Web Integration Guide
-
-> Complete walkthrough for testing, purchasing, and integrating the license system with the desktop app.
-
----
-
-## Table of Contents
-
-1. [Feature Checklist](#feature-checklist)
-2. [Environment Setup](#environment-setup)
-3. [Purchase Flow](#purchase-flow)
-4. [Desktop App Integration](#desktop-app-integration)
-5. [API Reference](#api-reference)
-6. [Testing Scenarios](#testing-scenarios)
-
----
-
-## Feature Checklist
-
-### Marketing Site
-
-| Page | Feature | Status |
-|------|---------|--------|
-| **Landing** | Hero section with animations | ⬜ |
-| **Landing** | Features grid (12 cards) | ⬜ |
-| **Landing** | Pricing cards (Free vs Pro) | ⬜ |
-| **Landing** | Comparison table | ⬜ |
-| **Landing** | FAQ accordion | ⬜ |
-| **Landing** | CTA section | ⬜ |
-| **Landing** | Footer with links | ⬜ |
-| **Landing** | Mobile responsive | ⬜ |
-| **Download** | Platform cards (macOS, Windows, Linux) | ⬜ |
-| **Download** | Download links work | ⬜ |
-| **Download** | System requirements shown | ⬜ |
-
-### Screenshots to Add
-
-Replace these placeholder locations with actual screenshots:
-
-| Location | File | Recommended Size |
-|----------|------|------------------|
-| Hero section | `public/screenshots/hero.png` | 1920×1080 |
-| Query Editor | `public/screenshots/editor.png` | 1200×750 |
-| ER Diagrams | `public/screenshots/erd.png` | 1200×750 |
-
-### Backend APIs
-
-| Endpoint | Test Command | Expected |
-|----------|--------------|----------|
-| License Validate | `curl -X POST /api/license/validate` | Returns validation status |
-| License Activate | `curl -X POST /api/license/activate` | Creates activation |
-| License Deactivate | `curl -X POST /api/license/deactivate` | Removes activation |
-| Update Check | `curl /api/updates/check?version=1.0.0` | Returns update info |
-| Dodo Webhook | POST with signature | Creates license |
-
----
-
-## Environment Setup
-
-### 1. Database (Supabase or Neon)
-
-```bash
-# Create a PostgreSQL database, then:
-cd apps/web
-cp .env.example .env.local
-```
-
-Add your database URL:
-```env
-DATABASE_URL="postgresql://user:password@host:5432/database?sslmode=require"
-```
-
-Run migrations:
-```bash
-pnpm db:push
-```
-
-### 2. Clerk Authentication
-
-1. Create account at [clerk.com](https://clerk.com)
-2. Create a new application
-3. Copy keys to `.env.local`:
-
-```env
-NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_..."
-CLERK_SECRET_KEY="sk_test_..."
-```
-
-### 3. DodoPayments
-
-1. Create account at [dodopayments.com](https://dodopayments.com)
-2. Create a product:
- - Name: `data-peek Pro License`
- - Type: One-time payment
- - Price: $29 (or $99 regular)
-3. Set up webhook:
- - URL: `https://your-domain.com/api/webhooks/dodo`
- - Events: `payment.completed`, `payment.refunded`
-4. Copy credentials:
-
-```env
-DODO_API_KEY="..."
-DODO_WEBHOOK_SECRET="..."
-```
-
-### 4. Resend (Email)
-
-1. Create account at [resend.com](https://resend.com)
-2. Verify your domain
-3. Create API key:
-
-```env
-RESEND_API_KEY="re_..."
-```
-
----
-
-## Purchase Flow
-
-### How It Works
-
-```
-┌─────────────────────────────────────────────────────────────────┐
-│ PURCHASE FLOW │
-├─────────────────────────────────────────────────────────────────┤
-│ │
-│ 1. User clicks "Get Pro — $29" on website │
-│ ↓ │
-│ 2. Redirected to DodoPayments checkout │
-│ ↓ │
-│ 3. User completes payment │
-│ ↓ │
-│ 4. DodoPayments sends webhook to /api/webhooks/dodo │
-│ ↓ │
-│ 5. Backend creates customer + license in database │
-│ ↓ │
-│ 6. Welcome email sent with license key │
-│ ↓ │
-│ 7. User enters key in desktop app → activated! │
-│ │
-└─────────────────────────────────────────────────────────────────┘
-```
-
-### License Key Format
-
-```
-DPRO-XXXX-XXXX-XXXX-XXXX
-```
-
-- Prefix: `DPRO` (Pro), `DTEAM` (Team), `DENT` (Enterprise)
-- 4 groups of 4 alphanumeric characters
-- No confusing characters (0, O, 1, I, l excluded)
-
-### Setting Up the Buy Button
-
-Update the pricing component to link to DodoPayments:
-
-```tsx
-// src/components/marketing/pricing.tsx
-
-// Replace href with your DodoPayments checkout link
-{
- cta: 'Get Pro License',
- href: 'https://checkout.dodopayments.com/buy/your-product-id',
- // Or use their SDK for embedded checkout
-}
-```
-
-### Testing Purchases Locally
-
-1. Use DodoPayments test mode
-2. Use webhook testing tool (ngrok or similar):
-
-```bash
-ngrok http 3000
-# Use the ngrok URL for webhook endpoint
-```
-
-3. Make a test purchase
-4. Check database for new license:
-
-```bash
-pnpm db:studio
-# Opens Drizzle Studio to inspect data
-```
-
----
-
-## Desktop App Integration
-
-### 1. Install Dependencies
-
-```bash
-cd apps/desktop
-pnpm add node-machine-id
-```
-
-### 2. Add License Types
-
-Create `src/shared/license.ts`:
-
-```typescript
-export interface LicenseInfo {
- valid: boolean
- plan: 'free' | 'pro' | 'team' | 'enterprise'
- status: 'active' | 'revoked' | 'expired'
- updatesUntil: string
- activationsUsed: number
- activationsMax: number
-}
-
-export interface ActivationInfo {
- id: string
- deviceId: string
- deviceName: string | null
- activatedAt: string
-}
-
-export interface ActivateResponse {
- success: boolean
- activation?: ActivationInfo
- license?: LicenseInfo
- error?: string
-}
-```
-
-### 3. Create License Service (Main Process)
-
-Create `src/main/license.ts`:
-
-```typescript
-import { machineIdSync } from 'node-machine-id'
-import { app } from 'electron'
-import Store from 'electron-store'
-import os from 'os'
-
-const store = new Store()
-const API_BASE = 'https://datapeek.app/api' // or your domain
-
-// Get unique device identifier
-export function getDeviceId(): string {
- return machineIdSync()
-}
-
-export function getDeviceInfo() {
- return {
- deviceId: getDeviceId(),
- deviceName: os.hostname(),
- os: process.platform, // darwin, win32, linux
- appVersion: app.getVersion(),
- }
-}
-
-// Validate license with server
-export async function validateLicense(licenseKey: string): Promise {
- const response = await fetch(`${API_BASE}/license/validate`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- licenseKey,
- deviceId: getDeviceId(),
- }),
- })
-
- return response.json()
-}
-
-// Activate license on this device
-export async function activateLicense(licenseKey: string): Promise {
- const deviceInfo = getDeviceInfo()
-
- const response = await fetch(`${API_BASE}/license/activate`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- licenseKey,
- ...deviceInfo,
- }),
- })
-
- const result = await response.json()
-
- if (result.success) {
- // Store license locally
- store.set('license', {
- key: licenseKey,
- ...result.license,
- lastValidated: new Date().toISOString(),
- })
- }
-
- return result
-}
-
-// Deactivate this device
-export async function deactivateLicense(licenseKey: string): Promise<{ success: boolean }> {
- const response = await fetch(`${API_BASE}/license/deactivate`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- licenseKey,
- deviceId: getDeviceId(),
- }),
- })
-
- if (response.ok) {
- store.delete('license')
- }
-
- return response.json()
-}
-
-// Get stored license
-export function getStoredLicense() {
- return store.get('license') as StoredLicense | undefined
-}
-
-// Check license on app startup
-export async function checkLicenseOnStartup(): Promise {
- const stored = getStoredLicense()
-
- if (!stored) {
- return { status: 'free', features: FREE_FEATURES }
- }
-
- try {
- // Try online validation
- const result = await validateLicense(stored.key)
-
- if (result.valid) {
- // Update cache
- store.set('license', {
- ...stored,
- ...result,
- lastValidated: new Date().toISOString(),
- })
- return { status: 'pro', features: PRO_FEATURES, license: result }
- } else {
- // License revoked or invalid
- store.delete('license')
- return { status: 'free', features: FREE_FEATURES, error: 'License invalid' }
- }
- } catch (error) {
- // Offline - use cached validation with grace period
- const lastValidated = new Date(stored.lastValidated)
- const gracePeriod = 14 * 24 * 60 * 60 * 1000 // 14 days
-
- if (Date.now() - lastValidated.getTime() < gracePeriod) {
- return { status: 'pro', features: PRO_FEATURES, offline: true }
- }
-
- return { status: 'free', features: FREE_FEATURES, error: 'License validation failed' }
- }
-}
-```
-
-### 4. Add IPC Handlers
-
-In `src/main/index.ts`:
-
-```typescript
-import {
- checkLicenseOnStartup,
- activateLicense,
- deactivateLicense,
- getStoredLicense,
-} from './license'
-
-// License IPC handlers
-ipcMain.handle('license:check', async () => {
- return checkLicenseOnStartup()
-})
-
-ipcMain.handle('license:activate', async (_, licenseKey: string) => {
- return activateLicense(licenseKey)
-})
-
-ipcMain.handle('license:deactivate', async (_, licenseKey: string) => {
- return deactivateLicense(licenseKey)
-})
-
-ipcMain.handle('license:get', async () => {
- return getStoredLicense()
-})
-```
-
-### 5. Update Preload Script
-
-In `src/preload/index.ts`:
-
-```typescript
-// Add to the API object
-license: {
- check: () => ipcRenderer.invoke('license:check'),
- activate: (key: string) => ipcRenderer.invoke('license:activate', key),
- deactivate: (key: string) => ipcRenderer.invoke('license:deactivate', key),
- get: () => ipcRenderer.invoke('license:get'),
-}
-```
-
-### 6. Create License Store (Renderer)
-
-Create `src/renderer/src/stores/license-store.ts`:
-
-```typescript
-import { create } from 'zustand'
-
-interface LicenseState {
- status: 'loading' | 'free' | 'pro' | 'team' | 'enterprise'
- license: LicenseInfo | null
- isOffline: boolean
- error: string | null
-
- // Actions
- checkLicense: () => Promise
- activateLicense: (key: string) => Promise<{ success: boolean; error?: string }>
- deactivateLicense: () => Promise
-
- // Feature checks
- isPro: () => boolean
- canUseFeature: (feature: string) => boolean
-}
-
-// Feature limits for free tier
-const FREE_LIMITS = {
- connections: 2,
- queryHistory: 50,
- tabs: 3,
- erDiagrams: 1,
-}
-
-export const useLicenseStore = create((set, get) => ({
- status: 'loading',
- license: null,
- isOffline: false,
- error: null,
-
- checkLicense: async () => {
- try {
- const result = await window.api.license.check()
- set({
- status: result.status,
- license: result.license ?? null,
- isOffline: result.offline ?? false,
- error: result.error ?? null,
- })
- } catch (error) {
- set({ status: 'free', error: 'Failed to check license' })
- }
- },
-
- activateLicense: async (key: string) => {
- try {
- const result = await window.api.license.activate(key)
- if (result.success) {
- set({
- status: result.license?.plan ?? 'pro',
- license: result.license ?? null,
- error: null,
- })
- return { success: true }
- }
- return { success: false, error: result.error }
- } catch (error) {
- return { success: false, error: 'Activation failed' }
- }
- },
-
- deactivateLicense: async () => {
- const license = get().license
- if (license) {
- await window.api.license.deactivate(license.key)
- }
- set({ status: 'free', license: null })
- },
-
- isPro: () => {
- const status = get().status
- return status === 'pro' || status === 'team' || status === 'enterprise'
- },
-
- canUseFeature: (feature: string) => {
- const isPro = get().isPro()
- if (isPro) return true
-
- // Check free tier limits
- switch (feature) {
- case 'unlimited-connections':
- case 'unlimited-history':
- case 'unlimited-tabs':
- case 'unlimited-erd':
- case 'inline-editing':
- case 'query-plans':
- return false
- default:
- return true
- }
- },
-}))
-```
-
-### 7. Create License Dialog Component
-
-Create `src/renderer/src/components/license-dialog.tsx`:
-
-```tsx
-import { useState } from 'react'
-import { useLicenseStore } from '@/stores/license-store'
-import {
- Dialog,
- DialogContent,
- DialogHeader,
- DialogTitle,
-} from '@/components/ui/dialog'
-import { Button } from '@/components/ui/button'
-import { Input } from '@/components/ui/input'
-import { Key, Check, AlertCircle, ExternalLink } from 'lucide-react'
-
-interface LicenseDialogProps {
- open: boolean
- onOpenChange: (open: boolean) => void
-}
-
-export function LicenseDialog({ open, onOpenChange }: LicenseDialogProps) {
- const [licenseKey, setLicenseKey] = useState('')
- const [isLoading, setIsLoading] = useState(false)
- const [error, setError] = useState(null)
-
- const { status, license, activateLicense, deactivateLicense } = useLicenseStore()
- const isPro = status !== 'free' && status !== 'loading'
-
- const handleActivate = async () => {
- if (!licenseKey.trim()) return
-
- setIsLoading(true)
- setError(null)
-
- const result = await activateLicense(licenseKey.trim())
-
- setIsLoading(false)
-
- if (result.success) {
- setLicenseKey('')
- onOpenChange(false)
- } else {
- setError(result.error ?? 'Activation failed')
- }
- }
-
- const handleDeactivate = async () => {
- setIsLoading(true)
- await deactivateLicense()
- setIsLoading(false)
- }
-
- return (
-
-
-
-
-
- License
-
-
-
- {isPro ? (
- // Pro license view
-
-
-
-
- Pro License Active
-
-
- Updates until: {new Date(license?.updatesUntil ?? '').toLocaleDateString()}
-
-
- Activations: {license?.activationsUsed} / {license?.activationsMax}
-
-
-
-
- Deactivate This Device
-
-
- ) : (
- // Free tier view
-
-
- License Key
- setLicenseKey(e.target.value.toUpperCase())}
- className="font-mono"
- />
-
-
- {error && (
-
- )}
-
-
- {isLoading ? 'Activating...' : 'Activate License'}
-
-
-
-
- )}
-
-
- )
-}
-```
-
-### 8. Feature Gating Example
-
-```tsx
-// Example: Gating the "Add Connection" button
-
-import { useLicenseStore } from '@/stores/license-store'
-
-function ConnectionList() {
- const { isPro, canUseFeature } = useLicenseStore()
- const connections = useConnectionStore((s) => s.connections)
-
- const canAddConnection = isPro() || connections.length < 2
-
- return (
-
- {/* ... connection list ... */}
-
-
- Add Connection
- {!canAddConnection && (
- Pro
- )}
-
-
- {!canAddConnection && (
-
- Free tier limited to 2 connections.
- Upgrade to Pro
-
- )}
-
- )
-}
-```
-
----
-
-## API Reference
-
-### POST /api/license/validate
-
-Validate a license key and check if device is activated.
-
-**Request:**
-```json
-{
- "licenseKey": "DPRO-XXXX-XXXX-XXXX-XXXX",
- "deviceId": "unique-machine-id"
-}
-```
-
-**Response:**
-```json
-{
- "valid": true,
- "plan": "pro",
- "status": "active",
- "updatesUntil": "2025-11-28T00:00:00.000Z",
- "activationsUsed": 1,
- "activationsMax": 3
-}
-```
-
-### POST /api/license/activate
-
-Activate a license on a new device.
-
-**Request:**
-```json
-{
- "licenseKey": "DPRO-XXXX-XXXX-XXXX-XXXX",
- "deviceId": "unique-machine-id",
- "deviceName": "MacBook Pro",
- "os": "darwin",
- "appVersion": "1.0.0"
-}
-```
-
-**Response:**
-```json
-{
- "success": true,
- "activation": {
- "id": "uuid",
- "deviceId": "unique-machine-id",
- "deviceName": "MacBook Pro",
- "activatedAt": "2024-11-28T00:00:00.000Z"
- },
- "license": {
- "plan": "pro",
- "updatesUntil": "2025-11-28T00:00:00.000Z",
- "activationsUsed": 1,
- "activationsMax": 3
- }
-}
-```
-
-### POST /api/license/deactivate
-
-Deactivate a device.
-
-**Request:**
-```json
-{
- "licenseKey": "DPRO-XXXX-XXXX-XXXX-XXXX",
- "deviceId": "unique-machine-id"
-}
-```
-
-**Response:**
-```json
-{
- "success": true,
- "activationsRemaining": 2
-}
-```
-
-### GET /api/updates/check
-
-Check for app updates.
-
-**Request:**
-```
-GET /api/updates/check?version=1.0.0&platform=macos-arm
-```
-
-**Response:**
-```json
-{
- "hasUpdate": true,
- "latestVersion": "1.1.0",
- "currentVersion": "1.0.0",
- "downloadUrl": "https://...",
- "releaseNotes": "Bug fixes and improvements",
- "forceUpdate": false
-}
-```
-
----
-
-## Testing Scenarios
-
-### Manual Test Checklist
-
-| Scenario | Steps | Expected Result |
-|----------|-------|-----------------|
-| **Fresh install (free)** | Open app with no license | Free tier limits apply |
-| **Valid activation** | Enter valid license key | Unlocks Pro features |
-| **Invalid key** | Enter random key | Shows error message |
-| **Max activations** | Activate on 4th device | Shows "max reached" error |
-| **Deactivate** | Deactivate from settings | Reverts to free tier |
-| **Offline mode** | Disconnect internet, open app | Uses cached license (14 day grace) |
-| **Revoked license** | Revoke via webhook | Shows "revoked" error on next validation |
-| **Update check** | Use older version | Shows update available |
-
-### Test License Keys
-
-For development, you can manually insert test licenses:
-
-```sql
--- Insert test customer
-INSERT INTO customers (email, name)
-VALUES ('test@example.com', 'Test User');
-
--- Insert test license (get customer ID from above)
-INSERT INTO licenses (customer_id, license_key, plan, status, max_activations, updates_until)
-VALUES (
- 'customer-uuid-here',
- 'DPRO-TEST-TEST-TEST-TEST',
- 'pro',
- 'active',
- 3,
- NOW() + INTERVAL '1 year'
-);
-```
-
----
-
-## Deployment Checklist
-
-- [ ] Database migrations run on production
-- [ ] Environment variables set on Vercel/hosting
-- [ ] DodoPayments webhook URL updated to production
-- [ ] Clerk production keys configured
-- [ ] Resend domain verified
-- [ ] Download links point to actual releases
-- [ ] Screenshots added to marketing site
-
----
-
-*Document created: November 2024*