diff --git a/PLANS.md b/PLANS.md deleted file mode 100644 index 90d9102..0000000 --- a/PLANS.md +++ /dev/null @@ -1,111 +0,0 @@ -# Warpbox Plans & Staged Development - -This document captures the staged development history and roadmap for Warpbox. For day-to-day usage, -configuration, and deployment, see [README.md](./README.md). - -## Stage 2 — Operator Tools - -- `/admin/login` - token-based admin login. -- `/admin` - overview metrics: boxes, files, storage, recent uploads, protected/expired boxes. -- `/admin/files` - recent upload table with view and delete actions. -- Expired boxes and boxes that have reached their download limit are cleaned on startup and then - every `WARPBOX_CLEANUP_EVERY` when `WARPBOX_CLEANUP_ENABLED=true`. -- Missing image/video thumbnails are generated in a background worker every `WARPBOX_THUMBNAIL_EVERY` - when `WARPBOX_THUMBNAIL_ENABLED=true`. - -## Stage 3 — Anonymous Integrations - -Anonymous uploads return a private management link at creation time. Keep that link secret: anyone -with it can delete the entire upload box. The raw delete token is not stored and cannot be recovered -later. - -Browser uploads still show `Open box` and `Copy URL` as the primary actions, with a smaller -`Manage or delete this upload` link in the completion panel. - -Curl and custom uploaders can use the same endpoint: - -```bash -# Terminal-friendly output: one plain box URL. -curl -F file=@./report.pdf http://localhost:8080/api/v1/upload - -# JSON output with boxUrl, thumbnailUrl, manageUrl, deleteUrl, zipUrl, and file entries. -curl -F sharex=@./screenshot.png \ - -H 'Accept: application/json' \ - http://localhost:8080/api/v1/upload -``` - -The upload endpoint accepts multipart fields named `file` and `sharex`. ShareX users can start from -`examples/sharex/warpbox-anonymous.sxcu`; update `RequestURL` to match your instance URL. -Authenticated uploads (your account's limits) add an `Authorization: Bearer ` header — mint a -token under **Account → Access tokens**. The JSON response uses ShareX placeholders `{json:boxUrl}` -(URL), `{json:thumbnailUrl}` (thumbnail), `{json:deleteUrl}` (deletion), and `{json:error}` (error -message). - -### Grouping multiple files into one box (`X-Warpbox-Batch`) - -By default every uploaded file becomes its own box. To put several files in a **single** box, send -the opt-in `X-Warpbox-Batch` header: requests that share the same header value (scoped per account, -or per IP for anonymous uploads) within 20s are appended to the same box. This lets a multi-file -ShareX selection — which ShareX sends as separate back-to-back requests — land as one shareable link. -The shipped `.sxcu` sets `X-Warpbox-Batch: sharex`; remove that header for one box per file. Requests -without the header behave exactly as before. - -### Resumable API flow - -Custom clients can use the resumable JSON API for large files: - -```bash -# 1. Create a resumable session from file metadata. -curl -s http://localhost:8080/api/v1/uploads/resumable \ - -H 'Accept: application/json' \ - -H 'Content-Type: application/json' \ - -d '{"files":[{"name":"large.bin","size":1048576,"contentType":"application/octet-stream"}],"expiresMinutes":1440}' - -# 2. Upload exact-sized chunks using the returned sessionId, file id, and chunkSize. -dd if=./large.bin bs=8388608 count=1 skip=0 2>/dev/null | \ - curl -X PUT --data-binary @- \ - http://localhost:8080/api/v1/uploads/resumable/SESSION_ID/files/FILE_ID/chunks/0 - -# 3. Complete the session after all chunks are present. -curl -X POST -H 'Accept: application/json' \ - http://localhost:8080/api/v1/uploads/resumable/SESSION_ID/complete -``` - -The complete response is the same JSON shape as `POST /api/v1/upload`, including `boxUrl`, -`manageUrl`, `deleteUrl`, and file URLs. Send `Authorization: Bearer ` on every resumable -request to upload as an account. - -Browser resumable uploads are configurable from `/admin/settings`: enabled/disabled, chunk size in -MB, draft retention hours, and chunk staging location. The default chunk mode stores temporary draft -chunks under `data/tmp/uploads/{session_id}`. A custom mode can point those chunks at another local -path, such as a mounted fast SSD. Chunk staging stays local even when the completed files are later -finalized into S3/SFTP/SMB/WebDAV storage. Completion returns the share link immediately; files may -show as `Processing` on the download page while the background finalizer streams them to the selected -storage backend. Cleanup removes expired uploading drafts but skips sessions already in processing. - -## Stage 4 — Accounts + Personal Boxes - -- `/register` bootstraps the first admin account only when no users exist. -- `/login` and `/logout` provide cookie-based web sessions. -- `/app` is the personal dashboard for logged-in users, showing owned boxes, storage usage, upload - history, and flat collections. Uploading still happens from the homepage. -- `/admin/users` lets admins create invite links, disable/reactivate users, and generate reset links. -- Logged-in browser uploads from `/` still use `POST /api/v1/upload`, but the resulting box is stored - with owner and optional collection metadata. -- Admin users are exempt from the global max upload size on the homepage upload flow. Future per-user - quotas should apply to this same upload path rather than creating a second uploader. -- `/admin/settings` controls anonymous uploads, anonymous max upload size, daily upload caps, default - user storage quota, and usage retention. -- `/admin/users` shows storage/daily usage and lets admins set per-user storage quota overrides. -- `/admin/storage` manages the built-in local file backend and S3-compatible bucket backends. -- `/admin/bans` manages manual IP/CIDR bans and optional automatic bans for suspicious probes and - repeated login failures. Auto-ban is off by default and configured from the admin UI. -- Upload limits now include daily bytes, daily box counts, active box counts, short-window request - limits, max expiration days, local storage capacity in GB, and per-user policy overrides. -- Uploaded file content, thumbnails, and private box metadata use the selected storage backend. The - bbolt database and JSON logs remain local under `./data/db` and `./data/logs`. -- Anonymous uploads, ShareX uploads, unlisted public box links, password protection, expiry, delete - tokens, thumbnails, and cleanup continue to work as before. - -Email delivery is intentionally deferred. Invite and reset links are copyable today; future SMTP -support will power public forgot-password and optional email delivery. diff --git a/backend/libs/handlers/accounts_test.go b/backend/libs/handlers/accounts_test.go index f66c991..2ee153b 100644 --- a/backend/libs/handlers/accounts_test.go +++ b/backend/libs/handlers/accounts_test.go @@ -68,7 +68,7 @@ func TestLoggedInUploadStoresOwnerAndAnonymousUploadDoesNot(t *testing.T) { } } if !foundOwned { - t.Fatalf("logged-in upload did not store owner id %q", user.ID) + t.Fatalf("logged in upload did not store owner id %q", user.ID) } } @@ -674,7 +674,7 @@ func TestAPIDocsHeaderReflectsLoggedInUser(t *testing.T) { body := response.Body.String() header := body[:strings.Index(body, " 0 || result.Failed > 0 { - logger.Info("thumbnail one-shot job complete", "source", "thumbnail", "severity", "user_activity", "code", 2205, "box_id", boxID, "generated", result.Generated, "failed", result.Failed) + logger.Info("thumbnail one shot job complete", "source", "thumbnail", "severity", "user_activity", "code", 2205, "box_id", boxID, "generated", result.Generated, "failed", result.Failed) } }() } diff --git a/backend/libs/services/auth.go b/backend/libs/services/auth.go index d2ebe84..0aa3100 100644 --- a/backend/libs/services/auth.go +++ b/backend/libs/services/auth.go @@ -120,7 +120,7 @@ type Collection struct { UpdatedAt time.Time `json:"updatedAt"` } -// APIToken is a long-lived personal access token. Only the SHA-256 hash of the +// APIToken is a long lived personal access token. Only the SHA-256 hash of the // secret is stored; the plaintext is shown to the user exactly once at creation. type APIToken struct { ID string `json:"id"` @@ -131,7 +131,7 @@ type APIToken struct { LastUsedAt *time.Time `json:"lastUsedAt,omitempty"` } -// APITokenResult carries the one-time plaintext alongside the stored token. +// APITokenResult carries the one time plaintext alongside the stored token. type APITokenResult struct { Token APIToken Plaintext string @@ -907,7 +907,7 @@ func validateUserPolicy(policy UserPolicy) error { return fmt.Errorf("active box override must be positive or -1 for unlimited") } if policy.ShortWindowRequests != nil && *policy.ShortWindowRequests <= 0 && *policy.ShortWindowRequests != -1 { - return fmt.Errorf("short-window request override must be positive or -1 for unlimited") + return fmt.Errorf("short window request override must be positive or -1 for unlimited") } return nil } diff --git a/backend/libs/services/auth_test.go b/backend/libs/services/auth_test.go index 0769818..cd4a53d 100644 --- a/backend/libs/services/auth_test.go +++ b/backend/libs/services/auth_test.go @@ -118,7 +118,7 @@ func TestAPITokenLifecycle(t *testing.T) { if result.Plaintext == "" || !strings.HasPrefix(result.Plaintext, apiTokenPrefix) { t.Fatalf("plaintext = %q, want %q prefix", result.Plaintext, apiTokenPrefix) } - // The secret must never be stored in plaintext — only its hash. + // The secret must never be stored in plaintext. only its hash. if strings.Contains(result.Token.TokenHash, result.Plaintext) || result.Token.TokenHash == result.Plaintext { t.Fatalf("stored token hash leaks the plaintext secret") } diff --git a/backend/libs/services/bans.go b/backend/libs/services/bans.go index 74ca312..7387d5e 100644 --- a/backend/libs/services/bans.go +++ b/backend/libs/services/bans.go @@ -313,7 +313,7 @@ func (s *BanService) Match(ip string, now time.Time) (MatchedBan, bool, error) { now = now.UTC() var matched BanRecord var matchedKey []byte - // Read-only scan first: the common case (no match) only takes a concurrent + // read only scan first: the common case (no match) only takes a concurrent // read transaction, instead of grabbing the single bbolt write lock on every // request that flows through the ban middleware. err := s.db.View(func(tx *bbolt.Tx) error { diff --git a/backend/libs/services/proxy.go b/backend/libs/services/proxy.go index 686e127..a6b2ca4 100644 --- a/backend/libs/services/proxy.go +++ b/backend/libs/services/proxy.go @@ -19,7 +19,7 @@ func ClientIPFromContext(r *http.Request) (string, bool) { } // ClientIP resolves the effective client IP. When trustedProxies is empty, -// forwarded headers are trusted for easy reverse-proxy/container defaults. +// forwarded headers are trusted for easy reverse proxy/container defaults. func ClientIP(remoteAddr, forwardedFor, realIP string, trustedProxies []string) string { remoteIP := IPOnly(remoteAddr) if len(trustedProxies) == 0 || remoteTrusted(remoteIP, trustedProxies) { diff --git a/backend/libs/services/settings.go b/backend/libs/services/settings.go index 34a745c..91d9460 100644 --- a/backend/libs/services/settings.go +++ b/backend/libs/services/settings.go @@ -455,7 +455,7 @@ func (s *SettingsService) validate(settings UploadPolicySettings) error { return fmt.Errorf("active box limits must be positive") } if settings.ShortWindowRequests <= 0 || settings.ShortWindowSeconds <= 0 { - return fmt.Errorf("short-window rate limits must be positive") + return fmt.Errorf("short window rate limits must be positive") } if settings.ResumableChunkSizeMB <= 0 { return fmt.Errorf("resumable chunk size must be positive") diff --git a/backend/libs/services/upload.go b/backend/libs/services/upload.go index 21525ad..04ddd40 100644 --- a/backend/libs/services/upload.go +++ b/backend/libs/services/upload.go @@ -306,7 +306,7 @@ func (s *UploadService) CreateBoxFromIncomingContext(ctx context.Context, files var expiresAt time.Time switch { case opts.ExpiresInMinutes < 0 || opts.MaxDays < 0: - // "Forever" — a date far enough out that the box effectively never + // "Forever". a date far enough out that the box effectively never // expires. No schema change; CanDownload/cleanup keep working as-is. expiresAt = now.AddDate(100, 0, 0) case opts.ExpiresInMinutes > 0: @@ -361,7 +361,7 @@ func (s *UploadService) CreateBoxFromIncomingContext(ctx context.Context, files return s.resultForBox(box, deleteToken), nil } -// AppendFiles adds files to an existing box (used to group a ShareX multi-file +// AppendFiles adds files to an existing box (used to group a ShareX multiple file // selection into a single box). The box keeps its original expiry, password and // other settings; only the new files are written. func (s *UploadService) AppendFiles(boxID string, files []*multipart.FileHeader, opts UploadOptions) (UploadResult, error) { @@ -1099,7 +1099,7 @@ func (s *UploadService) resultForBox(box Box, deleteToken string) UploadResult { } // The box-level thumbnail points at the most recently added file, so a - // per-file ShareX upload previews the file it just sent. + // per file ShareX upload previews the file it just sent. thumbnailURL := fmt.Sprintf("%s/d/%s/og-image.jpg", s.baseURL, box.ID) if len(files) > 0 { thumbnailURL = files[len(files)-1].ThumbnailURL diff --git a/backend/static/css/00-base.css b/backend/static/css/00-base.css index a9d896a..1696e4b 100644 --- a/backend/static/css/00-base.css +++ b/backend/static/css/00-base.css @@ -18,7 +18,7 @@ --danger: #fb7185; --radius: 0.875rem; --shadow: 0 24px 70px rgba(8, 4, 32, 0.6); - --font-sans: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-sans: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans serif; --header-bg: rgba(11, 11, 22, 0.68); --body-bg: radial-gradient(circle at 50% -10%, rgba(139, 92, 246, 0.18), transparent 34rem), @@ -48,7 +48,7 @@ --danger: #fca5a5; --radius: 0.625rem; --shadow: 0 24px 70px rgba(0, 0, 0, 0.45); - --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans serif; --header-bg: rgba(9, 9, 11, 0.84); --body-bg: radial-gradient(circle at 50% -10%, rgba(82, 82, 91, 0.32), transparent 34rem), @@ -78,7 +78,7 @@ --danger: #fb4934; --radius: 0.65rem; --shadow: 0 24px 70px rgba(0, 0, 0, 0.42); - --font-sans: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-sans: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans serif; --header-bg: rgba(29, 32, 33, 0.86); --body-bg: radial-gradient(circle at 20% -8%, rgba(215, 153, 33, 0.2), transparent 28rem), @@ -109,7 +109,7 @@ --danger: #ff2a6d; --radius: 0.35rem; --shadow: 0 24px 70px rgba(255, 42, 109, 0.16), 0 0 34px rgba(0, 240, 255, 0.12); - --font-sans: "Inter", "Rajdhani", "Orbitron", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --font-sans: "Inter", "Rajdhani", "Orbitron", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans serif; --header-bg: rgba(8, 7, 13, 0.86); --body-bg: radial-gradient(circle at 10% -10%, rgba(255, 242, 0, 0.2), transparent 26rem), @@ -145,7 +145,7 @@ inset 1px 1px 0 #ffffff, inset -2px -2px 0 #808080, inset 2px 2px 0 #dfdfdf; - --font-sans: "PixeloidSans", "PixelOperator", "Microsoft Sans Serif", Tahoma, sans-serif; + --font-sans: "PixeloidSans", "PixelOperator", "Microsoft Sans Serif", Tahoma, sans serif; --header-bg: #c0c0c0; --body-bg: #000000; --surface-1: #ffffff; diff --git a/backend/static/css/04-dialogs.css b/backend/static/css/04-dialogs.css index 9ad64a8..522d9c2 100644 --- a/backend/static/css/04-dialogs.css +++ b/backend/static/css/04-dialogs.css @@ -189,7 +189,7 @@ html.warpbox-dialog-open body { background: #c0c0c0; color: #000000; box-shadow: inset -1px -1px 0 #404040, inset 1px 1px 0 #ffffff, inset -2px -2px 0 #808080, inset 2px 2px 0 #dfdfdf, 4px 4px 0 rgba(0, 0, 0, 0.45); - font-family: "PixeloidSans", "PixelOperator", "Microsoft Sans Serif", Tahoma, sans-serif; + font-family: "PixeloidSans", "PixelOperator", "Microsoft Sans Serif", Tahoma, sans serif; } :root[data-theme="retro"] .warpbox-dialog-head { diff --git a/backend/static/css/16-retro.css b/backend/static/css/16-retro.css index ef17fe0..7739090 100644 --- a/backend/static/css/16-retro.css +++ b/backend/static/css/16-retro.css @@ -1,16 +1,16 @@ /* - * "retro" theme flourishes — modelled on danlegt.com. + * "retro" theme flourishes. Modelled on danlegt.com. * * Windows 98 chrome over a black pixel-star desktop, PixeloidSans pixel font, * crisp (non-antialiased, pixelated) rendering. Scoped entirely to * :root[data-theme="retro"] so it never touches the other themes. * - * CSP-safe: external stylesheet + self-hosted fonts only (font-src 'self'), + * CSP-safe: external stylesheet + self hosted fonts only (font-src 'self'), * no inline styles, no remote assets. The starfield is pure CSS so we don't * depend on img-src for a background gif. */ -/* Self-hosted pixel fonts (mirrored locally — GGBotNet PixeloidSans is free, +/* self hosted pixel fonts (mirrored locally. GGBotNet PixeloidSans is free, PixelOperator is CC0). ------------------------------------------------- */ @font-face { font-family: "PixeloidSans"; @@ -50,7 +50,7 @@ image-rendering: pixelated; } -/* Square everything — Win98 had no rounded corners. */ +/* Square everything. Win98 had no rounded corners. */ :root[data-theme="retro"] *, :root[data-theme="retro"] *::before, :root[data-theme="retro"] *::after { @@ -736,7 +736,7 @@ align-self: start; } -:root[data-theme="retro"] .file-type, +:root[data-theme="retro"] .file type, :root[data-theme="retro"] .file-size, :root[data-theme="retro"] .file-main small { color: inherit; diff --git a/backend/static/css/19-popups.css b/backend/static/css/19-popups.css index 03c0fd1..93f09e2 100644 --- a/backend/static/css/19-popups.css +++ b/backend/static/css/19-popups.css @@ -97,7 +97,7 @@ :root[data-theme="retro"] .warpbox-popups { inset-block-start: 2.65rem; - font-family: "PixeloidSans", "PixelOperator", "Microsoft Sans Serif", Tahoma, sans-serif; + font-family: "PixeloidSans", "PixelOperator", "Microsoft Sans Serif", Tahoma, sans serif; } :root[data-theme="retro"] .warpbox-popup { diff --git a/backend/static/css/30-download.css b/backend/static/css/30-download.css index 258e087..035bac1 100644 --- a/backend/static/css/30-download.css +++ b/backend/static/css/30-download.css @@ -1285,7 +1285,7 @@ html.reaction-picker-open body { object-fit: contain; } -/* Retro (Win98) icons are tiny pixel art — keep them crisp and swap them in +/* Retro (Win98) icons are tiny pixel art. Keep them crisp and swap them in only when the retro theme is active. */ .file-icon-retro { display: none; @@ -1318,7 +1318,7 @@ html.reaction-picker-open body { white-space: nowrap; } -.file-type, +.file type, .file-size { overflow: hidden; color: var(--muted-foreground); @@ -1401,7 +1401,7 @@ html.reaction-picker-open body { padding-top: 0.25rem; } -.file-browser.is-thumbs .file-type, +.file-browser.is-thumbs .file type, .file-browser.is-thumbs .file-size { display: none; } diff --git a/backend/static/css/40-docs.css b/backend/static/css/40-docs.css index 2c86a86..e670aa1 100644 --- a/backend/static/css/40-docs.css +++ b/backend/static/css/40-docs.css @@ -11,7 +11,7 @@ } /* ============================================================ - API documentation — sidebar layout + API documentation: sidebar layout ============================================================ */ .api-docs { @@ -315,6 +315,7 @@ .method-get { background: #2563eb; } .method-post { background: #16a34a; } .method-put { background: #d97706; } +.method-delete { background: #dc2626; } .endpoint-list { display: flex; diff --git a/backend/static/css/80-markdown-preview.css b/backend/static/css/80-markdown-preview.css index bcf28be..51e0ac5 100644 --- a/backend/static/css/80-markdown-preview.css +++ b/backend/static/css/80-markdown-preview.css @@ -13,7 +13,7 @@ --md-block-code-fg: #f8fafc; --md-block-code-border: rgba(248, 250, 252, 0.16); --md-shadow: rgba(0, 0, 0, 0.28); - --md-font: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --md-font: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans serif; --md-mono: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; } @@ -48,7 +48,7 @@ --md-block-code-fg: #f5f5f5; --md-block-code-border: #808080; --md-shadow: transparent; - --md-font: "PixeloidSans", "PixelOperator", "Microsoft Sans Serif", Tahoma, sans-serif; + --md-font: "PixeloidSans", "PixelOperator", "Microsoft Sans Serif", Tahoma, sans serif; --md-mono: "PixelOperatorMono", Consolas, monospace; } diff --git a/backend/static/css/90-responsive.css b/backend/static/css/90-responsive.css index 72045f1..3ee2aa4 100644 --- a/backend/static/css/90-responsive.css +++ b/backend/static/css/90-responsive.css @@ -160,7 +160,7 @@ grid-template-columns: 3rem minmax(0, 1fr) auto; } - .file-type { + .file type { display: none; } diff --git a/backend/static/js/05-theme.js b/backend/static/js/05-theme.js index 72d2da7..b43c852 100644 --- a/backend/static/js/05-theme.js +++ b/backend/static/js/05-theme.js @@ -6,8 +6,8 @@ * localStorage (no cookie, no server round-trip) and applies site-wide. * * CSP note: this is an external /static file, so it is allowed under - * script-src 'self'. We only toggle an attribute / class — never inject inline - * - - -
-

This page didn't load

-

Something went wrong on our end. You can try refreshing or head back home.

-
- - Go home -
-
- -`; -} diff --git a/docs/Mock-Up/Mockup Magic/src/lib/mock-data.ts b/docs/Mock-Up/Mockup Magic/src/lib/mock-data.ts deleted file mode 100644 index 7b046c1..0000000 --- a/docs/Mock-Up/Mockup Magic/src/lib/mock-data.ts +++ /dev/null @@ -1,53 +0,0 @@ -export type MockFile = { - id: string; - name: string; - size: string; - uploaded: string; - expires: string; - downloads: number; - status: "Active" | "Expired" | "Flagged"; - owner: string; - folder?: string; -}; - -export const mockFiles: MockFile[] = [ - { id: "a1b2c3", name: "design-spec-v4.pdf", size: "2.1 MB", uploaded: "2h ago", expires: "in 7d", downloads: 12, status: "Active", owner: "you", folder: "Projects" }, - { id: "d4e5f6", name: "team-photo.jpg", size: "5.8 MB", uploaded: "1d ago", expires: "in 6d", downloads: 47, status: "Active", owner: "you", folder: "Projects" }, - { id: "g7h8i9", name: "backup-2026-05.tar.gz", size: "1.2 GB", uploaded: "3d ago", expires: "in 27d", downloads: 2, status: "Active", owner: "you", folder: "Backups" }, - { id: "j0k1l2", name: "client-brief.docx", size: "84 KB", uploaded: "5d ago", expires: "expired", downloads: 8, status: "Expired", owner: "anon-104.x.x", folder: "Projects/Client A" }, - { id: "m3n4o5", name: "screen-recording.mp4", size: "312 MB", uploaded: "1w ago", expires: "in 23d", downloads: 134, status: "Flagged", owner: "anon-188.x.x" }, - { id: "p6q7r8", name: "invoice-2026-05.pdf", size: "96 KB", uploaded: "2w ago", expires: "in 16d", downloads: 3, status: "Active", owner: "alice@acme.dev" }, -]; - -export const mockFolders = [ - { name: "Projects", children: [{ name: "Client A" }, { name: "Client B" }, { name: "Internal" }] }, - { name: "Backups", children: [] }, - { name: "Media", children: [{ name: "Photos" }, { name: "Video" }] }, - { name: "Archive", children: [] }, -]; - -export const mockUsers = [ - { email: "alice@acme.dev", role: "Admin", storage: "4.2 GB / 50 GB", files: 184, status: "Active", joined: "2025-11-02" }, - { email: "bob@workshop.io", role: "User", storage: "812 MB / 10 GB", files: 41, status: "Active", joined: "2026-01-14" }, - { email: "carol@startup.app", role: "User", storage: "9.8 GB / 10 GB", files: 612, status: "Active", joined: "2026-03-08" }, - { email: "dan@example.com", role: "User", storage: "12 MB / 10 GB", files: 3, status: "Suspended", joined: "2026-04-22" }, -]; - -export const mockLogs = [ - { ts: "12:42:18", level: "info", msg: "Upload completed bucket=a1b2c3 size=2.1MB" }, - { ts: "12:41:55", level: "warn", msg: "Rate limit hit ip=104.x.x.x" }, - { ts: "12:40:02", level: "info", msg: "User alice@acme.dev signed in" }, - { ts: "12:38:11", level: "error", msg: "S3 putObject retry (attempt 2)" }, - { ts: "12:35:00", level: "info", msg: "Cleanup removed 14 expired buckets" }, - { ts: "12:31:47", level: "info", msg: "Download bucket=g7h8i9 ip=188.x.x.x" }, -]; - -export const uploadTrend = [ - { day: "Mon", uploads: 124, downloads: 412 }, - { day: "Tue", uploads: 88, downloads: 380 }, - { day: "Wed", uploads: 156, downloads: 540 }, - { day: "Thu", uploads: 201, downloads: 612 }, - { day: "Fri", uploads: 178, downloads: 498 }, - { day: "Sat", uploads: 62, downloads: 220 }, - { day: "Sun", uploads: 44, downloads: 188 }, -]; \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/lib/utils.ts b/docs/Mock-Up/Mockup Magic/src/lib/utils.ts deleted file mode 100644 index a5ef193..0000000 --- a/docs/Mock-Up/Mockup Magic/src/lib/utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { clsx, type ClassValue } from "clsx"; -import { twMerge } from "tailwind-merge"; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} diff --git a/docs/Mock-Up/Mockup Magic/src/routeTree.gen.ts b/docs/Mock-Up/Mockup Magic/src/routeTree.gen.ts deleted file mode 100644 index 1c98693..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routeTree.gen.ts +++ /dev/null @@ -1,388 +0,0 @@ -/* eslint-disable */ - -// @ts-nocheck - -// noinspection JSUnusedGlobalSymbols - -// This file was automatically generated by TanStack Router. -// You should NOT make any changes in this file as it will be overwritten. -// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. - -import { Route as rootRouteImport } from './routes/__root' -import { Route as RegisterRouteImport } from './routes/register' -import { Route as LoginRouteImport } from './routes/login' -import { Route as DocsRouteImport } from './routes/docs' -import { Route as AboutRouteImport } from './routes/about' -import { Route as IndexRouteImport } from './routes/index' -import { Route as DIdRouteImport } from './routes/d.$id' -import { Route as AppSharedRouteImport } from './routes/app.shared' -import { Route as AppSettingsRouteImport } from './routes/app.settings' -import { Route as AppFilesRouteImport } from './routes/app.files' -import { Route as AppDashboardRouteImport } from './routes/app.dashboard' -import { Route as AdminUsersRouteImport } from './routes/admin.users' -import { Route as AdminStorageRouteImport } from './routes/admin.storage' -import { Route as AdminSettingsRouteImport } from './routes/admin.settings' -import { Route as AdminOverviewRouteImport } from './routes/admin.overview' -import { Route as AdminLogsRouteImport } from './routes/admin.logs' -import { Route as AdminFilesRouteImport } from './routes/admin.files' - -const RegisterRoute = RegisterRouteImport.update({ - id: '/register', - path: '/register', - getParentRoute: () => rootRouteImport, -} as any) -const LoginRoute = LoginRouteImport.update({ - id: '/login', - path: '/login', - getParentRoute: () => rootRouteImport, -} as any) -const DocsRoute = DocsRouteImport.update({ - id: '/docs', - path: '/docs', - getParentRoute: () => rootRouteImport, -} as any) -const AboutRoute = AboutRouteImport.update({ - id: '/about', - path: '/about', - getParentRoute: () => rootRouteImport, -} as any) -const IndexRoute = IndexRouteImport.update({ - id: '/', - path: '/', - getParentRoute: () => rootRouteImport, -} as any) -const DIdRoute = DIdRouteImport.update({ - id: '/d/$id', - path: '/d/$id', - getParentRoute: () => rootRouteImport, -} as any) -const AppSharedRoute = AppSharedRouteImport.update({ - id: '/app/shared', - path: '/app/shared', - getParentRoute: () => rootRouteImport, -} as any) -const AppSettingsRoute = AppSettingsRouteImport.update({ - id: '/app/settings', - path: '/app/settings', - getParentRoute: () => rootRouteImport, -} as any) -const AppFilesRoute = AppFilesRouteImport.update({ - id: '/app/files', - path: '/app/files', - getParentRoute: () => rootRouteImport, -} as any) -const AppDashboardRoute = AppDashboardRouteImport.update({ - id: '/app/dashboard', - path: '/app/dashboard', - getParentRoute: () => rootRouteImport, -} as any) -const AdminUsersRoute = AdminUsersRouteImport.update({ - id: '/admin/users', - path: '/admin/users', - getParentRoute: () => rootRouteImport, -} as any) -const AdminStorageRoute = AdminStorageRouteImport.update({ - id: '/admin/storage', - path: '/admin/storage', - getParentRoute: () => rootRouteImport, -} as any) -const AdminSettingsRoute = AdminSettingsRouteImport.update({ - id: '/admin/settings', - path: '/admin/settings', - getParentRoute: () => rootRouteImport, -} as any) -const AdminOverviewRoute = AdminOverviewRouteImport.update({ - id: '/admin/overview', - path: '/admin/overview', - getParentRoute: () => rootRouteImport, -} as any) -const AdminLogsRoute = AdminLogsRouteImport.update({ - id: '/admin/logs', - path: '/admin/logs', - getParentRoute: () => rootRouteImport, -} as any) -const AdminFilesRoute = AdminFilesRouteImport.update({ - id: '/admin/files', - path: '/admin/files', - getParentRoute: () => rootRouteImport, -} as any) - -export interface FileRoutesByFullPath { - '/': typeof IndexRoute - '/about': typeof AboutRoute - '/docs': typeof DocsRoute - '/login': typeof LoginRoute - '/register': typeof RegisterRoute - '/admin/files': typeof AdminFilesRoute - '/admin/logs': typeof AdminLogsRoute - '/admin/overview': typeof AdminOverviewRoute - '/admin/settings': typeof AdminSettingsRoute - '/admin/storage': typeof AdminStorageRoute - '/admin/users': typeof AdminUsersRoute - '/app/dashboard': typeof AppDashboardRoute - '/app/files': typeof AppFilesRoute - '/app/settings': typeof AppSettingsRoute - '/app/shared': typeof AppSharedRoute - '/d/$id': typeof DIdRoute -} -export interface FileRoutesByTo { - '/': typeof IndexRoute - '/about': typeof AboutRoute - '/docs': typeof DocsRoute - '/login': typeof LoginRoute - '/register': typeof RegisterRoute - '/admin/files': typeof AdminFilesRoute - '/admin/logs': typeof AdminLogsRoute - '/admin/overview': typeof AdminOverviewRoute - '/admin/settings': typeof AdminSettingsRoute - '/admin/storage': typeof AdminStorageRoute - '/admin/users': typeof AdminUsersRoute - '/app/dashboard': typeof AppDashboardRoute - '/app/files': typeof AppFilesRoute - '/app/settings': typeof AppSettingsRoute - '/app/shared': typeof AppSharedRoute - '/d/$id': typeof DIdRoute -} -export interface FileRoutesById { - __root__: typeof rootRouteImport - '/': typeof IndexRoute - '/about': typeof AboutRoute - '/docs': typeof DocsRoute - '/login': typeof LoginRoute - '/register': typeof RegisterRoute - '/admin/files': typeof AdminFilesRoute - '/admin/logs': typeof AdminLogsRoute - '/admin/overview': typeof AdminOverviewRoute - '/admin/settings': typeof AdminSettingsRoute - '/admin/storage': typeof AdminStorageRoute - '/admin/users': typeof AdminUsersRoute - '/app/dashboard': typeof AppDashboardRoute - '/app/files': typeof AppFilesRoute - '/app/settings': typeof AppSettingsRoute - '/app/shared': typeof AppSharedRoute - '/d/$id': typeof DIdRoute -} -export interface FileRouteTypes { - fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: - | '/' - | '/about' - | '/docs' - | '/login' - | '/register' - | '/admin/files' - | '/admin/logs' - | '/admin/overview' - | '/admin/settings' - | '/admin/storage' - | '/admin/users' - | '/app/dashboard' - | '/app/files' - | '/app/settings' - | '/app/shared' - | '/d/$id' - fileRoutesByTo: FileRoutesByTo - to: - | '/' - | '/about' - | '/docs' - | '/login' - | '/register' - | '/admin/files' - | '/admin/logs' - | '/admin/overview' - | '/admin/settings' - | '/admin/storage' - | '/admin/users' - | '/app/dashboard' - | '/app/files' - | '/app/settings' - | '/app/shared' - | '/d/$id' - id: - | '__root__' - | '/' - | '/about' - | '/docs' - | '/login' - | '/register' - | '/admin/files' - | '/admin/logs' - | '/admin/overview' - | '/admin/settings' - | '/admin/storage' - | '/admin/users' - | '/app/dashboard' - | '/app/files' - | '/app/settings' - | '/app/shared' - | '/d/$id' - fileRoutesById: FileRoutesById -} -export interface RootRouteChildren { - IndexRoute: typeof IndexRoute - AboutRoute: typeof AboutRoute - DocsRoute: typeof DocsRoute - LoginRoute: typeof LoginRoute - RegisterRoute: typeof RegisterRoute - AdminFilesRoute: typeof AdminFilesRoute - AdminLogsRoute: typeof AdminLogsRoute - AdminOverviewRoute: typeof AdminOverviewRoute - AdminSettingsRoute: typeof AdminSettingsRoute - AdminStorageRoute: typeof AdminStorageRoute - AdminUsersRoute: typeof AdminUsersRoute - AppDashboardRoute: typeof AppDashboardRoute - AppFilesRoute: typeof AppFilesRoute - AppSettingsRoute: typeof AppSettingsRoute - AppSharedRoute: typeof AppSharedRoute - DIdRoute: typeof DIdRoute -} - -declare module '@tanstack/react-router' { - interface FileRoutesByPath { - '/register': { - id: '/register' - path: '/register' - fullPath: '/register' - preLoaderRoute: typeof RegisterRouteImport - parentRoute: typeof rootRouteImport - } - '/login': { - id: '/login' - path: '/login' - fullPath: '/login' - preLoaderRoute: typeof LoginRouteImport - parentRoute: typeof rootRouteImport - } - '/docs': { - id: '/docs' - path: '/docs' - fullPath: '/docs' - preLoaderRoute: typeof DocsRouteImport - parentRoute: typeof rootRouteImport - } - '/about': { - id: '/about' - path: '/about' - fullPath: '/about' - preLoaderRoute: typeof AboutRouteImport - parentRoute: typeof rootRouteImport - } - '/': { - id: '/' - path: '/' - fullPath: '/' - preLoaderRoute: typeof IndexRouteImport - parentRoute: typeof rootRouteImport - } - '/d/$id': { - id: '/d/$id' - path: '/d/$id' - fullPath: '/d/$id' - preLoaderRoute: typeof DIdRouteImport - parentRoute: typeof rootRouteImport - } - '/app/shared': { - id: '/app/shared' - path: '/app/shared' - fullPath: '/app/shared' - preLoaderRoute: typeof AppSharedRouteImport - parentRoute: typeof rootRouteImport - } - '/app/settings': { - id: '/app/settings' - path: '/app/settings' - fullPath: '/app/settings' - preLoaderRoute: typeof AppSettingsRouteImport - parentRoute: typeof rootRouteImport - } - '/app/files': { - id: '/app/files' - path: '/app/files' - fullPath: '/app/files' - preLoaderRoute: typeof AppFilesRouteImport - parentRoute: typeof rootRouteImport - } - '/app/dashboard': { - id: '/app/dashboard' - path: '/app/dashboard' - fullPath: '/app/dashboard' - preLoaderRoute: typeof AppDashboardRouteImport - parentRoute: typeof rootRouteImport - } - '/admin/users': { - id: '/admin/users' - path: '/admin/users' - fullPath: '/admin/users' - preLoaderRoute: typeof AdminUsersRouteImport - parentRoute: typeof rootRouteImport - } - '/admin/storage': { - id: '/admin/storage' - path: '/admin/storage' - fullPath: '/admin/storage' - preLoaderRoute: typeof AdminStorageRouteImport - parentRoute: typeof rootRouteImport - } - '/admin/settings': { - id: '/admin/settings' - path: '/admin/settings' - fullPath: '/admin/settings' - preLoaderRoute: typeof AdminSettingsRouteImport - parentRoute: typeof rootRouteImport - } - '/admin/overview': { - id: '/admin/overview' - path: '/admin/overview' - fullPath: '/admin/overview' - preLoaderRoute: typeof AdminOverviewRouteImport - parentRoute: typeof rootRouteImport - } - '/admin/logs': { - id: '/admin/logs' - path: '/admin/logs' - fullPath: '/admin/logs' - preLoaderRoute: typeof AdminLogsRouteImport - parentRoute: typeof rootRouteImport - } - '/admin/files': { - id: '/admin/files' - path: '/admin/files' - fullPath: '/admin/files' - preLoaderRoute: typeof AdminFilesRouteImport - parentRoute: typeof rootRouteImport - } - } -} - -const rootRouteChildren: RootRouteChildren = { - IndexRoute: IndexRoute, - AboutRoute: AboutRoute, - DocsRoute: DocsRoute, - LoginRoute: LoginRoute, - RegisterRoute: RegisterRoute, - AdminFilesRoute: AdminFilesRoute, - AdminLogsRoute: AdminLogsRoute, - AdminOverviewRoute: AdminOverviewRoute, - AdminSettingsRoute: AdminSettingsRoute, - AdminStorageRoute: AdminStorageRoute, - AdminUsersRoute: AdminUsersRoute, - AppDashboardRoute: AppDashboardRoute, - AppFilesRoute: AppFilesRoute, - AppSettingsRoute: AppSettingsRoute, - AppSharedRoute: AppSharedRoute, - DIdRoute: DIdRoute, -} -export const routeTree = rootRouteImport - ._addFileChildren(rootRouteChildren) - ._addFileTypes() - -import type { getRouter } from './router.tsx' -import type { startInstance } from './start.ts' -declare module '@tanstack/react-start' { - interface Register { - ssr: true - router: Awaited> - config: Awaited> - } -} diff --git a/docs/Mock-Up/Mockup Magic/src/router.tsx b/docs/Mock-Up/Mockup Magic/src/router.tsx deleted file mode 100644 index 3423d59..0000000 --- a/docs/Mock-Up/Mockup Magic/src/router.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { QueryClient } from "@tanstack/react-query"; -import { createRouter } from "@tanstack/react-router"; -import { routeTree } from "./routeTree.gen"; - -export const getRouter = () => { - const queryClient = new QueryClient(); - - const router = createRouter({ - routeTree, - context: { queryClient }, - scrollRestoration: true, - defaultPreloadStaleTime: 0, - }); - - return router; -}; diff --git a/docs/Mock-Up/Mockup Magic/src/routes/__root.tsx b/docs/Mock-Up/Mockup Magic/src/routes/__root.tsx deleted file mode 100644 index aba7973..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/__root.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { - Outlet, - Link, - createRootRouteWithContext, - useRouter, - HeadContent, - Scripts, -} from "@tanstack/react-router"; - -import appCss from "../styles.css?url"; - -function NotFoundComponent() { - return ( -
-
-

404

-

Page not found

-

- The page you're looking for doesn't exist or has been moved. -

-
- - Go home - -
-
-
- ); -} - -function ErrorComponent({ error, reset }: { error: Error; reset: () => void }) { - console.error(error); - const router = useRouter(); - - return ( -
-
-

- This page didn't load -

-

- Something went wrong on our end. You can try refreshing or head back home. -

-
- - - Go home - -
-
-
- ); -} - -export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({ - head: () => ({ - meta: [ - { charSet: "utf-8" }, - { name: "viewport", content: "width=device-width, initial-scale=1" }, - { title: "Lovable App" }, - { name: "description", content: "Lovable Generated Project" }, - { name: "author", content: "Lovable" }, - { property: "og:title", content: "Lovable App" }, - { property: "og:description", content: "Lovable Generated Project" }, - { property: "og:type", content: "website" }, - { name: "twitter:card", content: "summary" }, - { name: "twitter:site", content: "@Lovable" }, - ], - links: [ - { - rel: "stylesheet", - href: appCss, - }, - ], - }), - shellComponent: RootShell, - component: RootComponent, - notFoundComponent: NotFoundComponent, - errorComponent: ErrorComponent, -}); - -function RootShell({ children }: { children: React.ReactNode }) { - return ( - - - - - - {children} - - - - ); -} - -function RootComponent() { - const { queryClient } = Route.useRouteContext(); - - return ( - - - - ); -} diff --git a/docs/Mock-Up/Mockup Magic/src/routes/about.tsx b/docs/Mock-Up/Mockup Magic/src/routes/about.tsx deleted file mode 100644 index fe27c8e..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/about.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { PublicHeader, Footer } from "@/components/layout/PublicHeader"; -import { Card, CardContent } from "@/components/ui/card"; -import { Shield, Zap, Server, Code2 } from "lucide-react"; - -export const Route = createFileRoute("/about")({ - head: () => ({ meta: [{ title: "About — warpbox.dev" }] }), - component: About, -}); - -const features = [ - { icon: Zap, title: "Fast", body: "Anonymous drop-and-share, no accounts needed. Resumable for large files." }, - { icon: Shield, title: "Private", body: "Password-protected buckets, expiry, max-downloads, optional one-time links." }, - { icon: Server, title: "Self-hosted", body: "Single Go binary or Docker. Local disk or S3-compatible storage." }, - { icon: Code2, title: "Automatable", body: "First-class curl, CLI, REST API and ShareX support." }, -]; - -function About() { - return ( -
- -
-

About warpbox.dev

-

- An open-source, self-hosted file transfer platform that pairs frictionless anonymous uploads - with optional accounts, folders, and a proper admin console. Built in Go with a minimal vanilla frontend. -

-
- {features.map((f) => ( - - - -

{f.title}

-

{f.body}

-
-
- ))} -
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/admin.files.tsx b/docs/Mock-Up/Mockup Magic/src/routes/admin.files.tsx deleted file mode 100644 index b1db334..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/admin.files.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; -import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { mockFiles } from "@/lib/mock-data"; - -export const Route = createFileRoute("/admin/files")({ - head: () => ({ meta: [{ title: "Admin · Files — warpbox.dev" }] }), - component: AdminFiles, -}); - -function AdminFiles() { - return ( - -
- - -
-
- - -
-
- - -
-
-
-
-
- - - -
-

{mockFiles.length} files

-
- - -
-
- - - - ID - Name - Owner - Size - Downloads - Status - - - - {mockFiles.map((f) => ( - - {f.id} - {f.name} - {f.owner} - {f.size} - {f.downloads} - {f.status} - - ))} - -
-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/admin.logs.tsx b/docs/Mock-Up/Mockup Magic/src/routes/admin.logs.tsx deleted file mode 100644 index 8a92a6e..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/admin.logs.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Badge } from "@/components/ui/badge"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { Input } from "@/components/ui/input"; -import { mockLogs } from "@/lib/mock-data"; - -export const Route = createFileRoute("/admin/logs")({ - head: () => ({ meta: [{ title: "Admin · Logs — warpbox.dev" }] }), - component: Logs, -}); - -function Logs() { - return ( - - - -
- - -
-
- {mockLogs.map((l, i) => ( -
- {l.ts} - - {l.level} - - {l.msg} -
- ))} -
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/admin.overview.tsx b/docs/Mock-Up/Mockup Magic/src/routes/admin.overview.tsx deleted file mode 100644 index 302e1bf..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/admin.overview.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; -import { Badge } from "@/components/ui/badge"; -import { Files, HardDrive, Upload, Download } from "lucide-react"; -import { mockFiles, uploadTrend } from "@/lib/mock-data"; -import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"; -import { Bar, BarChart, XAxis, YAxis, CartesianGrid } from "recharts"; - -export const Route = createFileRoute("/admin/overview")({ - head: () => ({ meta: [{ title: "Admin · Overview — warpbox.dev" }] }), - component: Overview, -}); - -const metrics = [ - { label: "Total files", value: "12,847", icon: Files }, - { label: "Total storage", value: "412 GB", icon: HardDrive }, - { label: "Uploads today", value: "287", icon: Upload }, - { label: "Downloads today", value: "3,128", icon: Download }, -]; - -function Overview() { - return ( - -
-
- {metrics.map((m) => ( - - -
- {m.label} - -
-
{m.value}
-
-
- ))} -
- - - -

Activity (last 7 days)

- - - - - - } /> - - - - -
-
- -
- - -
Recent uploads
- - FileOwnerSize - - {mockFiles.slice(0, 5).map((f) => ( - - {f.name} - {f.owner} - {f.size} - - ))} - -
-
-
- - - -
Recent flags
- - FileReasonStatus - - screen-recording.mp4TOS reportOpen - archive-z.zipAuto-scanReviewing - doc-final.pdfManualDismissed - -
-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/admin.settings.tsx b/docs/Mock-Up/Mockup Magic/src/routes/admin.settings.tsx deleted file mode 100644 index e2efe0a..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/admin.settings.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Switch } from "@/components/ui/switch"; -import { Separator } from "@/components/ui/separator"; - -export const Route = createFileRoute("/admin/settings")({ - head: () => ({ meta: [{ title: "Admin · Settings — warpbox.dev" }] }), - component: AdminSettings, -}); - -function AdminSettings() { - return ( - -
- - -

Instance branding

-
-
-
-
-
-
-
-
- - - -

Limits & retention

-
-
-
-
-
-
- -
- {[ - ["Allow anonymous uploads", true], - ["Allow registrations", true], - ["Require password on public links", false], - ["Show 'Powered by warpbox' footer", true], - ].map(([label, on]) => ( -
- {label as string} - -
- ))} -
-
-
-
- - - -

SMTP

-
-
-
-
-
-
-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/admin.storage.tsx b/docs/Mock-Up/Mockup Magic/src/routes/admin.storage.tsx deleted file mode 100644 index 87676eb..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/admin.storage.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Progress } from "@/components/ui/progress"; -import { Button } from "@/components/ui/button"; -import { Badge } from "@/components/ui/badge"; -import { HardDrive, Cloud } from "lucide-react"; - -export const Route = createFileRoute("/admin/storage")({ - head: () => ({ meta: [{ title: "Admin · Storage — warpbox.dev" }] }), - component: Storage, -}); - -function Storage() { - return ( - -
- - -

Local disk

Primary
-

/var/lib/warpbox/data

-
-
Used412 GB / 1 TB
- -
-
-
- - -

S3 backend

Mirror
-

s3://warpbox-archive · eu-central-1

-
-
Synced388 GB
- -
-
-
- - -

Cleanup

-

Run housekeeping for expired buckets and orphaned chunks.

-
- - - -
-

Last run: 14 minutes ago · 47 buckets removed · 312 MB reclaimed

-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/admin.users.tsx b/docs/Mock-Up/Mockup Magic/src/routes/admin.users.tsx deleted file mode 100644 index bf38a68..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/admin.users.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; -import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; -import { mockUsers } from "@/lib/mock-data"; - -export const Route = createFileRoute("/admin/users")({ - head: () => ({ meta: [{ title: "Admin · Users — warpbox.dev" }] }), - component: Users, -}); - -function Users() { - return ( - - - -
-

{mockUsers.length} users

- -
- - - - Email - Role - Storage - Files - Joined - Status - - - - - {mockUsers.map((u) => ( - - {u.email} - {u.role} - {u.storage} - {u.files} - {u.joined} - {u.status} - - - ))} - -
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/app.dashboard.tsx b/docs/Mock-Up/Mockup Magic/src/routes/app.dashboard.tsx deleted file mode 100644 index b4ef486..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/app.dashboard.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; -import { Badge } from "@/components/ui/badge"; -import { Button } from "@/components/ui/button"; -import { Upload, HardDrive, FileText, Download } from "lucide-react"; -import { mockFiles } from "@/lib/mock-data"; - -export const Route = createFileRoute("/app/dashboard")({ - head: () => ({ meta: [{ title: "Dashboard — warpbox.dev" }] }), - component: Dashboard, -}); - -const metrics = [ - { label: "Storage used", value: "4.2 GB", sub: "of 50 GB", icon: HardDrive }, - { label: "Total files", value: "184", sub: "+12 this week", icon: FileText }, - { label: "Downloads (7d)", value: "1,238", sub: "+18%", icon: Download }, - { label: "Active links", value: "27", sub: "3 expire soon", icon: Upload }, -]; - -function Dashboard() { - return ( - -
-
- {metrics.map((m) => ( - - -
- {m.label} - -
-
{m.value}
-
{m.sub}
-
-
- ))} -
- - - -
-

Recent uploads

- -
- - - - Name - Size - Uploaded - Expires - Downloads - Status - - - - {mockFiles.slice(0, 5).map((f) => ( - - {f.name} - {f.size} - {f.uploaded} - {f.expires} - {f.downloads} - - - {f.status} - - - - ))} - -
-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/app.files.tsx b/docs/Mock-Up/Mockup Magic/src/routes/app.files.tsx deleted file mode 100644 index a7608de..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/app.files.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Badge } from "@/components/ui/badge"; -import { - Table, TableBody, TableCell, TableHead, TableHeader, TableRow, -} from "@/components/ui/table"; -import { - Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbSeparator, -} from "@/components/ui/breadcrumb"; -import { - ChevronRight, Folder, FolderPlus, Search, Share2, Upload, MoreHorizontal, -} from "lucide-react"; -import { mockFiles, mockFolders } from "@/lib/mock-data"; - -export const Route = createFileRoute("/app/files")({ - head: () => ({ meta: [{ title: "My files — warpbox.dev" }] }), - component: Files, -}); - -function Files() { - return ( - -
- - -
Folders
-
-
- My files -
- {mockFolders.map((f) => ( -
-
- {f.name} -
- {f.children.map((c) => ( -
- {c.name} -
- ))} -
- ))} -
-
-
- -
-
- - - My files - - Projects - - -
-
- - -
- - - -
-
- - - - - - - Name - Size - Modified - Visibility - - - - - {mockFolders.slice(0, 2).map((f) => ( - - {f.name} - - 2d ago - Private - - - ))} - {mockFiles.map((f) => ( - - {f.name} - {f.size} - {f.uploaded} - - - {f.status === "Active" ? "Link" : f.status} - - - - - ))} - -
-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/app.settings.tsx b/docs/Mock-Up/Mockup Magic/src/routes/app.settings.tsx deleted file mode 100644 index 2c1b3cd..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/app.settings.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Separator } from "@/components/ui/separator"; -import { Badge } from "@/components/ui/badge"; - -export const Route = createFileRoute("/app/settings")({ - head: () => ({ meta: [{ title: "Settings — warpbox.dev" }] }), - component: Settings, -}); - -function Settings() { - return ( - -
- - -

Profile

-

Your account info.

-
-
-
-
-
-
-
- - - -

Password

-
-
-
-
-
-
-
- - - -

API tokens

-

Use for curl, CLI, or ShareX uploads.

- -
- {["cli-laptop", "sharex-desktop"].map((t) => ( -
-
-
{t}
-
Created 12 days ago · last used 2h ago
-
-
- read+write - -
-
- ))} -
-
- - -
-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/app.shared.tsx b/docs/Mock-Up/Mockup Magic/src/routes/app.shared.tsx deleted file mode 100644 index f77a388..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/app.shared.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { AppShell } from "@/components/layout/AppShell"; -import { Card, CardContent } from "@/components/ui/card"; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; -import { Button } from "@/components/ui/button"; -import { Badge } from "@/components/ui/badge"; -import { Copy, Trash2 } from "lucide-react"; -import { mockFiles } from "@/lib/mock-data"; - -export const Route = createFileRoute("/app/shared")({ - head: () => ({ meta: [{ title: "Shared links — warpbox.dev" }] }), - component: Shared, -}); - -function Shared() { - return ( - - - - - - - Link - File - Downloads - Expires - Protection - - - - - {mockFiles.map((f) => ( - - /d/{f.id} - {f.name} - {f.downloads} - {f.expires} - - {f.id.length % 2 ? "Password" : "Public"} - - -
- - -
-
-
- ))} -
-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/d.$id.tsx b/docs/Mock-Up/Mockup Magic/src/routes/d.$id.tsx deleted file mode 100644 index 756b83d..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/d.$id.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { createFileRoute, Link } from "@tanstack/react-router"; -import { Download, FileText, Lock, Clock, Box } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { Badge } from "@/components/ui/badge"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { MockupNav } from "@/components/layout/MockupNav"; - -export const Route = createFileRoute("/d/$id")({ - head: () => ({ meta: [{ title: "Download — warpbox.dev" }] }), - component: DownloadPage, -}); - -function DownloadPage() { - const { id } = Route.useParams(); - return ( -
-
- - warpbox.dev - -
-
-
-
- - -
- -
-

design-spec-v4.pdf

-

2.1 MB · PDF document

-
- Expires in 6d - 12 / 50 downloads -
- -

Bucket id: {id}

-
-
- - - -
- Password protected (variant) -
-
-
- - -
- -
-
-
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/docs.tsx b/docs/Mock-Up/Mockup Magic/src/routes/docs.tsx deleted file mode 100644 index 52abc96..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/docs.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { PublicHeader, Footer } from "@/components/layout/PublicHeader"; -import { Card, CardContent } from "@/components/ui/card"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; - -export const Route = createFileRoute("/docs")({ - head: () => ({ meta: [{ title: "Docs — warpbox.dev" }] }), - component: Docs, -}); - -function Block({ children }: { children: string }) { - return ( -
-      {children}
-    
- ); -} - -function Docs() { - return ( -
- -
-

Documentation

-

Quick start for uploading via the web, curl, CLI, and ShareX.

- - - - - - curl - CLI - REST API - ShareX - - - {`# Upload a file anonymously -curl --upload-file ./report.pdf https://warpbox.dev/ -# → https://warpbox.dev/d/a1b2c3/report.pdf`} - - - {`# Install -brew install warpbox - -# Upload with options -warpbox push ./video.mp4 --expires 7d --max-downloads 10 --password hunter2`} - - - {`POST /api/v1/uploads -Authorization: Bearer -Content-Type: multipart/form-data - -{ - "expires_in": "7d", - "max_downloads": 10, - "password": "optional" -}`} - - - {`{ - "Name": "warpbox.dev", - "DestinationType": "ImageUploader, FileUploader", - "RequestMethod": "POST", - "RequestURL": "https://warpbox.dev/api/v1/uploads", - "Body": "MultipartFormData", - "FileFormName": "file", - "URL": "{json:url}" -}`} - - - - -
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/index.tsx b/docs/Mock-Up/Mockup Magic/src/routes/index.tsx deleted file mode 100644 index 7679d4f..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/index.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { useState } from "react"; -import { UploadCloud, Copy, Check, ChevronDown, Lock, Clock, Hash } from "lucide-react"; -import { PublicHeader, Footer } from "@/components/layout/PublicHeader"; -import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Progress } from "@/components/ui/progress"; -import { Badge } from "@/components/ui/badge"; -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "@/components/ui/collapsible"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; - -export const Route = createFileRoute("/")({ - head: () => ({ - meta: [ - { title: "warpbox.dev — Self-hosted file transfer" }, - { name: "description", content: "Drop a file, share a link. Anonymous, encrypted, self-hosted." }, - ], - }), - component: Index, -}); - -const sampleUploads = [ - { name: "design-spec-v4.pdf", size: "2.1 MB", url: "https://warpbox.dev/d/a1b2c3" }, - { name: "team-photo.jpg", size: "5.8 MB", url: "https://warpbox.dev/d/d4e5f6" }, -]; - -function Index() { - const [copied, setCopied] = useState(null); - - const copy = (url: string) => { - navigator.clipboard?.writeText(url); - setCopied(url); - setTimeout(() => setCopied(null), 1500); - }; - - return ( -
- -
-
-

Send a file. Get a link.

-

- Anonymous, encrypted, self-hosted. No account required. -

-
- - - -
- -

Drop files to upload

-

or click to browse

-
- Max file size: 5 GB - · - Link expires in 7 days -
-
- - - - - - -
- - -
-
- - -
-
- - -
-
-
-
-
- - {/* Post-upload summary mock */} - - -
-
-
- - Upload complete -
-

- 2 files · expires in 7 days · 10 downloads max -

-
-
- - -
-
-
- {sampleUploads.map((f) => ( -
-
-
- {f.name} - {f.size} -
- {f.url} -
- -
- ))} -
-
-
- backup-2026-05.tar.gz - 62% -
- -
-
-
-
-
-
-
-
- ); -} diff --git a/docs/Mock-Up/Mockup Magic/src/routes/login.tsx b/docs/Mock-Up/Mockup Magic/src/routes/login.tsx deleted file mode 100644 index 46fed4f..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/login.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { createFileRoute, Link } from "@tanstack/react-router"; -import { Box } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { MockupNav } from "@/components/layout/MockupNav"; - -export const Route = createFileRoute("/login")({ - head: () => ({ meta: [{ title: "Sign in — warpbox.dev" }] }), - component: Login, -}); - -function Login() { - return ( -
-
- - warpbox.dev - - - -

Sign in

-

Welcome back.

-
-
- - -
-
- - -
- -
-
- Create account - Back to home -
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/routes/register.tsx b/docs/Mock-Up/Mockup Magic/src/routes/register.tsx deleted file mode 100644 index 738833a..0000000 --- a/docs/Mock-Up/Mockup Magic/src/routes/register.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { createFileRoute, Link } from "@tanstack/react-router"; -import { Box } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { MockupNav } from "@/components/layout/MockupNav"; - -export const Route = createFileRoute("/register")({ - head: () => ({ meta: [{ title: "Create account — warpbox.dev" }] }), - component: Register, -}); - -function Register() { - return ( -
-
- - warpbox.dev - - - -

Create account

-

Free, self-hosted instance.

-
-
- - -
-
- - -
-
- - -
- -
-
- Sign in instead - Back to home -
-
-
-
- ); -} \ No newline at end of file diff --git a/docs/Mock-Up/Mockup Magic/src/server.ts b/docs/Mock-Up/Mockup Magic/src/server.ts deleted file mode 100644 index 2451322..0000000 --- a/docs/Mock-Up/Mockup Magic/src/server.ts +++ /dev/null @@ -1,80 +0,0 @@ -import "./lib/error-capture"; - -import { consumeLastCapturedError } from "./lib/error-capture"; -import { renderErrorPage } from "./lib/error-page"; - -type ServerEntry = { - fetch: (request: Request, env: unknown, ctx: unknown) => Promise | Response; -}; - -let serverEntryPromise: Promise | undefined; - -async function getServerEntry(): Promise { - if (!serverEntryPromise) { - serverEntryPromise = import("@tanstack/react-start/server-entry").then( - (m) => ((m as { default?: ServerEntry }).default ?? (m as unknown as ServerEntry)), - ); - } - return serverEntryPromise; -} - -function brandedErrorResponse(): Response { - return new Response(renderErrorPage(), { - status: 500, - headers: { "content-type": "text/html; charset=utf-8" }, - }); -} - -function isCatastrophicSsrErrorBody(body: string, responseStatus: number): boolean { - let payload: unknown; - try { - payload = JSON.parse(body); - } catch { - return false; - } - - if (!payload || Array.isArray(payload) || typeof payload !== "object") { - return false; - } - - const fields = payload as Record; - const expectedKeys = new Set(["message", "status", "unhandled"]); - if (!Object.keys(fields).every((key) => expectedKeys.has(key))) { - return false; - } - - return ( - fields.unhandled === true && - fields.message === "HTTPError" && - (fields.status === undefined || fields.status === responseStatus) - ); -} - -// h3 swallows in-handler throws into a normal 500 Response with body -// {"unhandled":true,"message":"HTTPError"} — try/catch alone never fires for those. -async function normalizeCatastrophicSsrResponse(response: Response): Promise { - if (response.status < 500) return response; - const contentType = response.headers.get("content-type") ?? ""; - if (!contentType.includes("application/json")) return response; - - const body = await response.clone().text(); - if (!isCatastrophicSsrErrorBody(body, response.status)) { - return response; - } - - console.error(consumeLastCapturedError() ?? new Error(`h3 swallowed SSR error: ${body}`)); - return brandedErrorResponse(); -} - -export default { - async fetch(request: Request, env: unknown, ctx: unknown) { - try { - const handler = await getServerEntry(); - const response = await handler.fetch(request, env, ctx); - return await normalizeCatastrophicSsrResponse(response); - } catch (error) { - console.error(error); - return brandedErrorResponse(); - } - }, -}; diff --git a/docs/Mock-Up/Mockup Magic/src/start.ts b/docs/Mock-Up/Mockup Magic/src/start.ts deleted file mode 100644 index d6152ee..0000000 --- a/docs/Mock-Up/Mockup Magic/src/start.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createStart, createMiddleware } from "@tanstack/react-start"; - -import { renderErrorPage } from "./lib/error-page"; - -const errorMiddleware = createMiddleware().server(async ({ next }) => { - try { - return await next(); - } catch (error) { - if (error != null && typeof error === "object" && "statusCode" in error) { - throw error; - } - console.error(error); - return new Response(renderErrorPage(), { - status: 500, - headers: { "content-type": "text/html; charset=utf-8" }, - }); - } -}); - -export const startInstance = createStart(() => ({ - requestMiddleware: [errorMiddleware], -})); diff --git a/docs/Mock-Up/Mockup Magic/src/styles.css b/docs/Mock-Up/Mockup Magic/src/styles.css deleted file mode 100644 index a9806b4..0000000 --- a/docs/Mock-Up/Mockup Magic/src/styles.css +++ /dev/null @@ -1,144 +0,0 @@ -@import "tailwindcss" source(none); -@source "../src"; -@import "tw-animate-css"; - -@custom-variant dark (&:is(.dark *)); - -/* - * Design system definition. - * - * The @theme inline block maps CSS custom properties to Tailwind utility - * classes (e.g. --color-primary -> bg-primary, text-primary). - * - * The :root and .dark blocks define the actual color values using oklch. - * All colors MUST use oklch format. - * - * To add a new semantic color: - * 1. Add the variable to :root (light value) and .dark (dark value) - * 2. Register it in @theme inline as --color-: var(--) - */ - -@theme inline { - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); - --radius-2xl: calc(var(--radius) + 8px); - --radius-3xl: calc(var(--radius) + 12px); - --radius-4xl: calc(var(--radius) + 16px); - --color-background: var(--background); - --color-foreground: var(--foreground); - --color-card: var(--card); - --color-card-foreground: var(--card-foreground); - --color-popover: var(--popover); - --color-popover-foreground: var(--popover-foreground); - --color-primary: var(--primary); - --color-primary-foreground: var(--primary-foreground); - --color-secondary: var(--secondary); - --color-secondary-foreground: var(--secondary-foreground); - --color-muted: var(--muted); - --color-muted-foreground: var(--muted-foreground); - --color-accent: var(--accent); - --color-accent-foreground: var(--accent-foreground); - --color-destructive: var(--destructive); - --color-destructive-foreground: var(--destructive-foreground); - --color-border: var(--border); - --color-input: var(--input); - --color-ring: var(--ring); - --color-ring-offset-background: var(--background); - --color-chart-1: var(--chart-1); - --color-chart-2: var(--chart-2); - --color-chart-3: var(--chart-3); - --color-chart-4: var(--chart-4); - --color-chart-5: var(--chart-5); - --color-sidebar: var(--sidebar); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-ring: var(--sidebar-ring); -} - -:root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.129 0.042 264.695); - --card: oklch(1 0 0); - --card-foreground: oklch(0.129 0.042 264.695); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.129 0.042 264.695); - --primary: oklch(0.208 0.042 265.755); - --primary-foreground: oklch(0.984 0.003 247.858); - --secondary: oklch(0.968 0.007 247.896); - --secondary-foreground: oklch(0.208 0.042 265.755); - --muted: oklch(0.968 0.007 247.896); - --muted-foreground: oklch(0.554 0.046 257.417); - --accent: oklch(0.968 0.007 247.896); - --accent-foreground: oklch(0.208 0.042 265.755); - --destructive: oklch(0.577 0.245 27.325); - --destructive-foreground: oklch(0.984 0.003 247.858); - --border: oklch(0.929 0.013 255.508); - --input: oklch(0.929 0.013 255.508); - --ring: oklch(0.704 0.04 256.788); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.984 0.003 247.858); - --sidebar-foreground: oklch(0.129 0.042 264.695); - --sidebar-primary: oklch(0.208 0.042 265.755); - --sidebar-primary-foreground: oklch(0.984 0.003 247.858); - --sidebar-accent: oklch(0.968 0.007 247.896); - --sidebar-accent-foreground: oklch(0.208 0.042 265.755); - --sidebar-border: oklch(0.929 0.013 255.508); - --sidebar-ring: oklch(0.704 0.04 256.788); -} - -.dark { - --background: oklch(0.129 0.042 264.695); - --foreground: oklch(0.984 0.003 247.858); - --card: oklch(0.208 0.042 265.755); - --card-foreground: oklch(0.984 0.003 247.858); - --popover: oklch(0.208 0.042 265.755); - --popover-foreground: oklch(0.984 0.003 247.858); - --primary: oklch(0.929 0.013 255.508); - --primary-foreground: oklch(0.208 0.042 265.755); - --secondary: oklch(0.279 0.041 260.031); - --secondary-foreground: oklch(0.984 0.003 247.858); - --muted: oklch(0.279 0.041 260.031); - --muted-foreground: oklch(0.704 0.04 256.788); - --accent: oklch(0.279 0.041 260.031); - --accent-foreground: oklch(0.984 0.003 247.858); - --destructive: oklch(0.704 0.191 22.216); - --destructive-foreground: oklch(0.984 0.003 247.858); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.551 0.027 264.364); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.208 0.042 265.755); - --sidebar-foreground: oklch(0.984 0.003 247.858); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.984 0.003 247.858); - --sidebar-accent: oklch(0.279 0.041 260.031); - --sidebar-accent-foreground: oklch(0.984 0.003 247.858); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.551 0.027 264.364); -} - -@layer base { - * { - border-color: var(--color-border); - } - - body { - background-color: var(--color-background); - color: var(--color-foreground); - } -} diff --git a/docs/Mock-Up/Mockup Magic/tsconfig.json b/docs/Mock-Up/Mockup Magic/tsconfig.json deleted file mode 100644 index 533d401..0000000 --- a/docs/Mock-Up/Mockup Magic/tsconfig.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "include": ["src/**/*.ts", "src/**/*.tsx", "vite.config.ts", "eslint.config.js"], - "compilerOptions": { - "target": "ES2022", - "jsx": "react-jsx", - "module": "ESNext", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "types": ["vite/client"], - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": false, - "noEmit": true, - - /* Linting */ - "skipLibCheck": true, - "strict": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true, - "paths": { - "@/*": ["./src/*"] - } - } -} diff --git a/docs/Mock-Up/Mockup Magic/vite.config.ts b/docs/Mock-Up/Mockup Magic/vite.config.ts deleted file mode 100644 index 6c77de3..0000000 --- a/docs/Mock-Up/Mockup Magic/vite.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -// @lovable.dev/vite-tanstack-config already includes the following — do NOT add them manually -// or the app will break with duplicate plugins: -// - tanstackStart, viteReact, tailwindcss, tsConfigPaths, cloudflare (build-only), -// componentTagger (dev-only), VITE_* env injection, @ path alias, React/TanStack dedupe, -// error logger plugins, and sandbox detection (port/host/strictPort). -// You can pass additional config via defineConfig({ vite: { ... } }) if needed. -import { defineConfig } from "@lovable.dev/vite-tanstack-config"; - -// Redirect TanStack Start's bundled server entry to src/server.ts (our SSR error wrapper). -// @cloudflare/vite-plugin builds from this — wrangler.jsonc main alone is insufficient. -export default defineConfig({ - tanstackStart: { - server: { entry: "server" }, - }, -}); diff --git a/docs/Mock-Up/Mockup Magic/wrangler.jsonc b/docs/Mock-Up/Mockup Magic/wrangler.jsonc deleted file mode 100644 index ebb5721..0000000 --- a/docs/Mock-Up/Mockup Magic/wrangler.jsonc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "node_modules/wrangler/config-schema.json", - "name": "tanstack-start-app", - "compatibility_date": "2025-09-24", - "compatibility_flags": ["nodejs_compat"], - "main": "src/server.ts", -} diff --git a/examples/sharex/warpbox-anonymous.sxcu b/examples/sharex/warpbox-anonymous.sxcu deleted file mode 100644 index 4f4d5b4..0000000 --- a/examples/sharex/warpbox-anonymous.sxcu +++ /dev/null @@ -1,17 +0,0 @@ -{ - "Version": "18.0.0", - "Name": "Warpbox Anonymous Upload", - "DestinationType": "ImageUploader, TextUploader, FileUploader", - "RequestMethod": "POST", - "RequestURL": "https://warpbox.dev/api/v1/upload", - "Headers": { - "Accept": "application/json", - "X-Warpbox-Batch": "sharex" - }, - "Body": "MultipartFormData", - "FileFormName": "sharex", - "URL": "{json:boxUrl}", - "ThumbnailURL": "{json:thumbnailUrl}", - "DeletionURL": "{json:deleteUrl}", - "ErrorMessage": "{json:error}" -}