feat: initial website commit + installation guide page

- Full nixpanel-website monorepo: web (React/Vite) + api (Fastify)
- Add /install page with one-liner, manual steps, requirements,
  software table, firewall ports, service management, and update/uninstall
- Add Install link to header nav and footer
- Add 'Install guide' CTA button to home page hero
- Add 'outline' variant to Button component
- Add .gitignore and .gitattributes

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
NixReaper
2026-04-05 11:16:42 -05:00
co-authored by Claude Sonnet 4.6
commit 72f5cc1060
48 changed files with 2695 additions and 0 deletions
+55
View File
@@ -0,0 +1,55 @@
-- NixPanel Website — Customer Schema
-- MariaDB / MySQL compatible
CREATE TABLE IF NOT EXISTS customers (
id VARCHAR(36) NOT NULL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
full_name VARCHAR(255) NOT NULL,
is_verified TINYINT(1) NOT NULL DEFAULT 0,
verify_token VARCHAR(128) NULL,
reset_token VARCHAR(128) NULL,
reset_token_expires DATETIME NULL,
stripe_customer_id VARCHAR(100) NULL UNIQUE,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_email (email),
INDEX idx_stripe_customer (stripe_customer_id)
);
CREATE TABLE IF NOT EXISTS subscriptions (
id VARCHAR(36) NOT NULL PRIMARY KEY,
customer_id VARCHAR(36) NOT NULL,
license_id VARCHAR(36) NOT NULL,
stripe_subscription_id VARCHAR(100) NOT NULL UNIQUE,
stripe_price_id VARCHAR(100) NOT NULL,
plan_key ENUM('free','solo','host','agency') NOT NULL DEFAULT 'free',
billing_interval ENUM('monthly','annual') NOT NULL DEFAULT 'monthly',
status ENUM('active','past_due','canceled','incomplete','trialing') NOT NULL DEFAULT 'active',
server_ip VARCHAR(45) NOT NULL,
current_period_start DATETIME NOT NULL,
current_period_end DATETIME NOT NULL,
cancel_at_period_end TINYINT(1) NOT NULL DEFAULT 0,
canceled_at DATETIME NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE,
INDEX idx_customer_id (customer_id),
INDEX idx_license_id (license_id),
INDEX idx_stripe_sub (stripe_subscription_id),
INDEX idx_server_ip (server_ip)
);
CREATE TABLE IF NOT EXISTS ip_change_requests (
id VARCHAR(36) NOT NULL PRIMARY KEY,
customer_id VARCHAR(36) NOT NULL,
subscription_id VARCHAR(36) NOT NULL,
old_ip VARCHAR(45) NOT NULL,
new_ip VARCHAR(45) NOT NULL,
status ENUM('pending','approved','rejected') NOT NULL DEFAULT 'pending',
requested_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
processed_at DATETIME NULL,
FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE CASCADE,
FOREIGN KEY (subscription_id) REFERENCES subscriptions(id) ON DELETE CASCADE,
INDEX idx_customer_id (customer_id)
);