A Chrome extension to quickly capture URLs into Semble Collections at https://semble.so
semble.so
at-proto
semble
chrome-extension
1<!DOCTYPE html>
2<html lang="en">
3
4<head>
5 <meta charset="UTF-8">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <title>Semble Quick Capture</title>
8 <link rel="preconnect" href="https://fonts.googleapis.com">
9 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10 <link href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700&display=swap"
11 rel="stylesheet">
12 <link rel="stylesheet" href="styles.css">
13</head>
14
15<body>
16 <!-- Auth Screen -->
17 <div id="loginScreen" class="screen hidden">
18 <div class="container">
19 <h2 class="title">Semble Quick Capture</h2>
20 <p class="subtitle">Sign in with your Bluesky account</p>
21
22 <form class="form-stack">
23 <div class="form-group">
24 <label class="form-label">@Handle</label>
25 <input type="text" id="loginHandle" placeholder="you.bsky.social" class="input-filled"
26 autocomplete="username">
27 </div>
28
29 <div class="form-group">
30 <label class="form-label">App Password</label>
31 <input type="password" id="loginPassword" placeholder="Your password" class="input-filled"
32 autocomplete="password">
33 <p class="form-hint">
34 Generate an <a href="https://bsky.app/settings/app-passwords" target="_blank" rel="noopener noreferrer"
35 class="form-link">App Password</a>. No account? <a href="https://bsky.app" target="_blank"
36 rel="noopener noreferrer" class="form-link">Sign up
37 on Bluesky</a>
38 </p>
39 </div>
40
41 <div class="form-group">
42 <label class="form-label">PDS Server (optional)</label>
43 <input type="text" id="loginService" placeholder="https://bsky.social" class="input-filled"
44 autocomplete="off">
45 <p class="form-hint">
46 Leave blank for default (bsky.social). Only change if you use a custom PDS server.
47 </p>
48 </div>
49
50 <button id="loginButton" type="button" class="btn btn-primary">
51 <span id="loginButtonText">Sign in</span>
52 <span id="loginButtonSpinner" class="btn-spinner hidden"></span>
53 </button>
54
55 <div id="loginError" class="alert alert-error hidden"></div>
56 </form>
57 </div>
58 </div>
59
60 <!-- Main Capture Screen -->
61 <div id="captureScreen" class="screen hidden">
62 <!-- Header -->
63 <div class="header">
64 <h1 class="header-title">Semble</h1>
65 <button id="logoutButton" class="btn-link">Sign Out</button>
66 </div>
67
68 <!-- Content -->
69 <div class="container">
70 <form class="form-stack">
71 <!-- URL Display -->
72 <div class="form-group">
73 <label class="form-label">URL</label>
74 <div class="url-display" id="currentUrl">Assembling...</div>
75 </div>
76
77 <!-- Note Input -->
78 <div class="form-group">
79 <label class="form-label">Note (optional)</label>
80 <textarea id="noteInput" rows="3" placeholder="Add your thoughts..." class="input-filled"></textarea>
81 </div>
82
83 <!-- Collection Dropdown -->
84 <div class="form-group">
85 <label class="form-label">Collection</label>
86 <select id="collectionSelect" class="input-filled">
87 <option value="">Assembling collections...</option>
88 </select>
89 </div>
90
91 <!-- Submit Button -->
92 <button id="submitButton" type="button" class="btn btn-primary" disabled>
93 Add to Collection
94 </button>
95
96 <!-- Status Message -->
97 <div id="statusMessage" class="alert hidden"></div>
98 </form>
99 </div>
100 </div>
101
102 <!-- Loading Screen -->
103 <div id="loadingScreen" class="screen">
104 <div class="loading-container">
105 <div class="spinner"></div>
106 <p class="loading-text">Assembling...</p>
107 </div>
108 </div>
109
110 <script src="popup.js"></script>
111</body>
112
113</html>