mobile bluesky app made with flutter
lazurite.stormlightlabs.org/
mobile
bluesky
flutter
1<!doctype html>
2<html lang="en">
3 <head>
4 <meta charset="UTF-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6 <meta name="description" content="Lazurite - A beautiful Material You Bluesky client for mobile and desktop" />
7 <meta name="author" content="Stormlight Labs" />
8 <title>Lazurite - Coming Soon</title>
9 <link rel="icon" type="image/svg+xml" href="static/favicon.svg" />
10 <link rel="preconnect" href="https://fonts.googleapis.com" />
11 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
12 <link
13 href="https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&family=DM+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
14 rel="stylesheet" />
15
16 <style>
17 :root {
18 --bg-dark: #161616;
19 --surface-dark: #262626;
20 --surface-variant: #393939;
21 --outline: #525252;
22 --text-primary: #f2f4f8;
23 --text-secondary: #dde1e6;
24 --text-tertiary: #697689;
25
26 --primary: #0085ff;
27 --secondary: #78a9ff;
28 --tertiary: #33b1ff;
29 --cyan: #08bdba;
30 --purple: #be95ff;
31
32 --font-display: "Lora", serif;
33 --font-body: "DM Sans", sans-serif;
34 --font-mono: "JetBrains Mono", monospace;
35 }
36
37 * {
38 margin: 0;
39 padding: 0;
40 box-sizing: border-box;
41 }
42
43 body {
44 font-family: var(--font-body);
45 background-color: var(--bg-dark);
46 color: var(--text-primary);
47 line-height: 1.6;
48 min-height: 100vh;
49 display: flex;
50 flex-direction: column;
51 }
52
53 .container {
54 max-width: 1200px;
55 margin: 0 auto;
56 padding: 2rem;
57 flex: 1;
58 display: flex;
59 flex-direction: column;
60 justify-content: center;
61 }
62
63 header {
64 text-align: center;
65 margin-bottom: 4rem;
66 }
67
68 .logo {
69 font-family: var(--font-display);
70 font-size: 3.5rem;
71 font-weight: 700;
72 background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 50%, var(--tertiary) 100%);
73 -webkit-background-clip: text;
74 -webkit-text-fill-color: transparent;
75 background-clip: text;
76 margin-bottom: 1rem;
77 letter-spacing: -0.02em;
78 }
79
80 .tagline {
81 font-size: 1.25rem;
82 color: var(--text-secondary);
83 font-weight: 400;
84 letter-spacing: 0.01em;
85 }
86
87 main {
88 max-width: 800px;
89 margin: 0 auto;
90 }
91
92 .hero {
93 text-align: center;
94 margin-bottom: 4rem;
95 }
96
97 .hero h1 {
98 font-family: var(--font-display);
99 font-size: 2.5rem;
100 font-weight: 600;
101 margin-bottom: 1.5rem;
102 color: var(--text-primary);
103 line-height: 1.2;
104 }
105
106 .hero p {
107 font-size: 1.125rem;
108 color: var(--text-secondary);
109 margin-bottom: 2rem;
110 line-height: 1.8;
111 }
112
113 .status-badge {
114 display: inline-flex;
115 align-items: center;
116 gap: 0.5rem;
117 background: var(--surface-dark);
118 padding: 0.75rem 1.5rem;
119 border-radius: 2rem;
120 border: 1px solid var(--outline);
121 font-size: 0.875rem;
122 font-weight: 500;
123 letter-spacing: 0.02em;
124 margin-bottom: 3rem;
125 }
126
127 .status-dot {
128 width: 8px;
129 height: 8px;
130 border-radius: 50%;
131 background: var(--primary);
132 animation: pulse 2s ease-in-out infinite;
133 }
134
135 @keyframes pulse {
136 0%,
137 100% {
138 opacity: 1;
139 }
140
141 50% {
142 opacity: 0.5;
143 }
144 }
145
146 .features {
147 display: grid;
148 grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
149 gap: 1.5rem;
150 margin-bottom: 4rem;
151 }
152
153 .feature {
154 background: var(--surface-dark);
155 padding: 2rem;
156 border-radius: 1rem;
157 border: 1px solid var(--outline);
158 transition:
159 transform 0.2s ease,
160 border-color 0.2s ease;
161 }
162
163 .feature:hover {
164 transform: translateY(-2px);
165 border-color: var(--primary);
166 }
167
168 .feature h3 {
169 font-family: var(--font-display);
170 font-size: 1.25rem;
171 margin-bottom: 0.75rem;
172 color: var(--text-primary);
173 }
174
175 .feature p {
176 color: var(--text-secondary);
177 font-size: 0.9375rem;
178 line-height: 1.6;
179 }
180
181 .feature-icon {
182 width: 48px;
183 height: 48px;
184 background: linear-gradient(135deg, var(--primary), var(--secondary));
185 border-radius: 12px;
186 display: flex;
187 align-items: center;
188 justify-content: center;
189 margin-bottom: 1rem;
190 padding: 12px;
191 }
192
193 .feature-icon img {
194 width: 100%;
195 height: 100%;
196 color: var(--bg-dark);
197 }
198
199 .tech-stack {
200 background: var(--surface-dark);
201 padding: 2rem;
202 border-radius: 1rem;
203 border: 1px solid var(--outline);
204 margin-bottom: 4rem;
205 }
206
207 .tech-stack h2 {
208 font-family: var(--font-display);
209 font-size: 1.5rem;
210 margin-bottom: 1.5rem;
211 color: var(--text-primary);
212 }
213
214 .tech-list {
215 display: flex;
216 flex-wrap: wrap;
217 gap: 0.75rem;
218 }
219
220 .tech-tag {
221 background: var(--surface-variant);
222 padding: 0.5rem 1rem;
223 border-radius: 0.5rem;
224 font-size: 0.875rem;
225 font-family: var(--font-mono);
226 color: var(--text-secondary);
227 border: 1px solid transparent;
228 transition: border-color 0.2s ease;
229 }
230
231 .tech-tag:hover {
232 border-color: var(--primary);
233 }
234
235 footer {
236 text-align: center;
237 padding: 2rem;
238 color: var(--text-tertiary);
239 font-size: 0.875rem;
240 border-top: 1px solid var(--outline);
241 margin-top: 4rem;
242 }
243
244 footer a {
245 color: var(--primary);
246 text-decoration: none;
247 transition: color 0.2s ease;
248 }
249
250 footer a:hover {
251 color: var(--secondary);
252 }
253
254 .oauth-info {
255 background: var(--surface-variant);
256 padding: 1rem 1.5rem;
257 border-radius: 0.75rem;
258 border-left: 3px solid var(--primary);
259 margin-top: 2rem;
260 font-size: 0.875rem;
261 color: var(--text-secondary);
262 }
263
264 .oauth-info a {
265 color: var(--primary);
266 text-decoration: none;
267 font-weight: 500;
268 transition: color 0.2s ease;
269 }
270
271 .oauth-info a:hover {
272 color: var(--secondary);
273 text-decoration: underline;
274 }
275
276 @media (max-width: 768px) {
277 .logo {
278 font-size: 2.5rem;
279 }
280
281 .hero h1 {
282 font-size: 2rem;
283 }
284
285 .hero p {
286 font-size: 1rem;
287 }
288
289 .features {
290 grid-template-columns: 1fr;
291 }
292
293 .container {
294 padding: 1.5rem;
295 }
296 }
297 </style>
298 </head>
299
300 <body>
301 <div class="container">
302 <header>
303 <div class="logo">Lazurite</div>
304 <p class="tagline">Coming Soon</p>
305 </header>
306
307 <main>
308 <div class="hero">
309 <div class="status-badge">
310 <span class="status-dot"></span>
311 <span>In Active Development</span>
312 </div>
313
314 <h1>A better BlueSky client</h1>
315 <p>
316 Lazurite is a cross-platform mobile and desktop client for Bluesky, with a mobile-first design for Android
317 and iOS, with desktop support for a seamless experience.
318 </p>
319 </div>
320
321 <div class="features">
322 <div class="feature">
323 <div class="feature-icon">
324 <img src="static/palette.svg" alt="Palette icon" />
325 </div>
326 <h3>Material You Design</h3>
327 <p>Beautiful IBM Oxocarbon-inspired theme with dynamic color adaptation and smooth animations.</p>
328 </div>
329
330 <div class="feature">
331 <div class="feature-icon">
332 <img src="static/message.svg" alt="Message icon" />
333 </div>
334 <h3>Full-Featured</h3>
335 <p>Timeline, threads, profiles, notifications, search, direct messages, and smart folders.</p>
336 </div>
337
338 <div class="feature">
339 <div class="feature-icon">
340 <img src="static/offline.svg" alt="Offline icon" />
341 </div>
342 <h3>Offline-First</h3>
343 <p>Smart caching with Drift database for lightning-fast performance and offline compose.</p>
344 </div>
345
346 <div class="feature">
347 <div class="feature-icon">
348 <img src="static/folder.svg" alt="Folder icon" />
349 </div>
350 <h3>Smart Folders</h3>
351 <p>Create custom local-only feeds with powerful filtering and organization tools.</p>
352 </div>
353 </div>
354
355 <div class="tech-stack">
356 <h2>Built with...</h2>
357 <div class="tech-list">
358 <span class="tech-tag">Flutter</span>
359 <span class="tech-tag">Dart</span>
360 <span class="tech-tag">Material 3</span>
361 <span class="tech-tag">AT Protocol</span>
362 </div>
363 </div>
364
365 <div class="oauth-info">
366 Follow development updates on Bluesky:
367 <a href="https://bsky.app/profile/desertthunder.dev" target="_blank" rel="noopener noreferrer"
368 >@desertthunder.dev</a
369 >
370 </div>
371 </main>
372 </div>
373
374 <footer>
375 <p>
376 Built with ⚡️ by
377 <a href="https://desertthunder.dev" target="_blank">Owais</a>
378 at
379 <a href="https://stormlightlabs.org" target="_blank">Stormlight Labs</a>
380 · Powered by the <a href="https://atproto.com" target="_blank">AT Protocol</a>
381 </p>
382 </footer>
383 </body>
384</html>