chore: added about to home screen and og info fe9051c1
Steve · 2025-11-05 11:31 13 file(s) · +116 −57
index.html +24 −2
2 2
<html lang="en">
3 3
  <head>
4 4
    <meta charset="UTF-8" />
5 -
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
5 +
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
6 +
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
7 +
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
8 +
    <link rel="manifest" href="/site.webmanifest">
6 9
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 -
    <title>alcove</title>
10 +
    <!-- HTML Meta Tags -->
11 +
    <title>Alcove</title>
12 +
    <meta name="description" content="A privacy focused RSS reader for the open web">
13 +
14 +
    <!-- Facebook Meta Tags -->
15 +
    <meta property="og:url" content="https://dev.alcove.tools">
16 +
    <meta property="og:type" content="website">
17 +
    <meta property="og:title" content="alcove">
18 +
    <meta property="og:description" content="A privacy focused RSS reader for the open web">
19 +
    <meta property="og:image" content="/og.png">
20 +
21 +
    <!-- Twitter Meta Tags -->
22 +
    <meta name="twitter:card" content="summary_large_image">
23 +
    <meta property="twitter:domain" content="dev.alcove.tools">
24 +
    <meta property="twitter:url" content="https://dev.alcove.tools">
25 +
    <meta name="twitter:title" content="alcove">
26 +
    <meta name="twitter:description" content="A privacy focused RSS reader for the open web">
27 +
    <meta name="twitter:image" content="/og.png">
28 +
29 +
    <!-- Meta Tags Generated via https://www.opengraph.xyz -->
8 30
  </head>
9 31
  <body style="margin: 0; background-color: oklch(0.1797 0.0043 308.1928);">
10 32
    <div id="root"></div>
public/android-chrome-192x192.png (added) +0 −0

Binary file — no preview.

public/android-chrome-512x512.png (added) +0 −0

Binary file — no preview.

public/apple-touch-icon.png (added) +0 −0

Binary file — no preview.

public/favicon-16x16.png (added) +0 −0

Binary file — no preview.

public/favicon-32x32.png (added) +0 −0

Binary file — no preview.

public/favicon.ico (added) +0 −0

Binary file — no preview.

public/icon.png (added) +0 −0

Binary file — no preview.

public/og.png (added) +0 −0

Binary file — no preview.

public/site.webmanifest (added) +1 −0
1 +
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
src/App.tsx +12 −4
23 23
	DialogHeader,
24 24
	DialogTitle,
25 25
} from "@/components/ui/dialog";
26 -
import { Upload, FileUp } from "lucide-react";
26 +
import { Upload, FileUp, Info } from "lucide-react";
27 27
import { Mnemonic } from "@evolu/common";
28 28
import { LoadingScreen } from "@/components/loading-screen";
29 +
import { AboutDialog } from "@/components/about-dialog";
29 30
30 31
function App() {
31 32
	const allFeeds = useQuery(allFeedsQuery);
250 251
				<div className="flex flex-col items-start justify-center gap-6 max-w-md w-full px-4">
251 252
					<div className="flex flex-col gap-2">
252 253
						<h1 className="text-4xl font-bold">Alcove</h1>
253 -
						<h4 className="sm:text-sm text-xs">
254 -
							A privacy focused RSS reader for the open web
255 -
						</h4>
254 +
						<div className="flex items-center gap-2">
255 +
							<h4 className="sm:text-sm text-xs">
256 +
								A privacy focused RSS reader for the open web
257 +
							</h4>
258 +
							<AboutDialog>
259 +
								<Button variant="ghost" size="icon" className="h-5 w-5">
260 +
									<Info className="sm:h-4 sm:w-4 h-2 w-2" />
261 +
								</Button>
262 +
							</AboutDialog>
263 +
						</div>
256 264
					</div>
257 265
					<div className="flex flex-col gap-3 w-full">
258 266
						<div className="flex flex-row gap-3 w-full">
src/components/about-dialog.tsx (added) +74 −0
1 +
import {
2 +
	Dialog,
3 +
	DialogContent,
4 +
	DialogHeader,
5 +
	DialogTitle,
6 +
	DialogTrigger,
7 +
} from "@/components/ui/dialog";
8 +
9 +
interface AboutDialogProps {
10 +
	open?: boolean;
11 +
	onOpenChange?: (open: boolean) => void;
12 +
	children?: React.ReactNode;
13 +
}
14 +
15 +
export function AboutDialog({
16 +
	open,
17 +
	onOpenChange,
18 +
	children,
19 +
}: AboutDialogProps) {
20 +
	return (
21 +
		<Dialog open={open} onOpenChange={onOpenChange}>
22 +
			{children && <DialogTrigger asChild>{children}</DialogTrigger>}
23 +
			<DialogContent>
24 +
				<DialogHeader>
25 +
					<DialogTitle>About</DialogTitle>
26 +
				</DialogHeader>
27 +
				<div className="space-y-4">
28 +
					<p className="text-sm text-muted-foreground">
29 +
						Alcove is built on two principles: privacy, and freedom of speech.
30 +
						Those two things are becoming harder to find these days, yet blogs
31 +
						and RSS feeds provides a way out. As long as someone is publishing
32 +
						and someone else is listening, these two fundamentals can help keep
33 +
						free speech alive. Alcove accomplishes privacy through a "can't be
34 +
						evil" tech stack, which you can read more about{" "}
35 +
						<a className="underline" target="_blank" rel="noreferrer" href="">
36 +
							here
37 +
						</a>
38 +
						. TLDR: all of your feeds and posts that you read are encrypted
39 +
						locally and synced via cryptographic keypairs. Even if we wanted to
40 +
						read your stuff, we can't.
41 +
					</p>
42 +
					<p className="text-sm text-muted-foreground">
43 +
						Due to how the encryption works, it is critical that you backup your
44 +
						account passphrase to a secure location like a password manager. If
45 +
						you clear your local browser data there is no way for us to recover
46 +
						your account or feeds, and you will need to make a new one. You can
47 +
						back it up in the settings page.
48 +
					</p>
49 +
					<p className="text-sm text-muted-foreground">
50 +
						Alcove is{" "}
51 +
						<a
52 +
							className="underline"
53 +
							href="https://github.com/stevedylandev/alcove"
54 +
							target="_blank"
55 +
							rel="noreferrer"
56 +
						>
57 +
							MIT open sourced
58 +
						</a>{" "}
59 +
						and run by{" "}
60 +
						<a
61 +
							className="underline"
62 +
							href="https://stevedylan.dev"
63 +
							target="_blank"
64 +
							rel="noreferrer"
65 +
						>
66 +
							Steve
67 +
						</a>
68 +
						.
69 +
					</p>
70 +
				</div>
71 +
			</DialogContent>
72 +
		</Dialog>
73 +
	);
74 +
}
src/components/nav-user.tsx +5 −51
46 46
	useSidebar,
47 47
} from "@/components/ui/sidebar";
48 48
import { Mnemonic } from "@evolu/common";
49 +
import { AboutDialog } from "@/components/about-dialog";
49 50
50 51
export function NavUser() {
51 52
	const { isMobile } = useSidebar();
344 345
					</div>
345 346
				</DialogContent>
346 347
			</Dialog>
347 -
			<Dialog open={isAboutDialogOpen} onOpenChange={setIsAboutDialogOpen}>
348 -
				<DialogContent>
349 -
					<DialogHeader>
350 -
						<DialogTitle>About</DialogTitle>
351 -
					</DialogHeader>
352 -
					<div className="space-y-4">
353 -
						<p className="text-sm text-muted-foreground">
354 -
							Alcove is built on two principles: privacy, and freedom of speech.
355 -
							Those two things are becoming harder to find these days, yet blogs
356 -
							and RSS feeds provides a way out. As long as someone is publishing
357 -
							and someone else is listening, these two fundamentals can help
358 -
							keep free speech alive. Alcove accomplishes privacy through a
359 -
							"can't be evil" tech stack, which you can read more about{" "}
360 -
							<a className="underline" target="_blank" rel="noreferrer" href="">
361 -
								here
362 -
							</a>
363 -
							. TLDR: all of your feeds and posts that you read are encrypted
364 -
							locally and synced via cryptographic keypairs. Even if we wanted
365 -
							to read your stuff, we can't.
366 -
						</p>
367 -
						<p className="text-sm text-muted-foreground">
368 -
							Due to how the encryption works, it is critical that you backup
369 -
							your account passphrase to a secure location like a password
370 -
							manager. If you clear your local browser data there is no way for
371 -
							us to recover your account or feeds, and you will need to make a
372 -
							new one. Back it up now in the settings page!
373 -
						</p>
374 -
						<p className="text-sm text-muted-foreground">
375 -
							Alcove is{" "}
376 -
							<a
377 -
								className="underline"
378 -
								href="https://github.com/stevedylandev/alcove"
379 -
								target="_blank"
380 -
								rel="noreferrer"
381 -
							>
382 -
								MIT open sourced
383 -
							</a>{" "}
384 -
							and run by{" "}
385 -
							<a
386 -
								className="underline"
387 -
								href="https://stevedylan.dev"
388 -
								target="_blank"
389 -
								rel="noreferrer"
390 -
							>
391 -
								Steve
392 -
							</a>
393 -
							.
394 -
						</p>
395 -
					</div>
396 -
				</DialogContent>
397 -
			</Dialog>
348 +
			<AboutDialog
349 +
				open={isAboutDialogOpen}
350 +
				onOpenChange={setIsAboutDialogOpen}
351 +
			/>
398 352
			<Dialog
399 353
				open={isImportOPMLDialogOpen}
400 354
				onOpenChange={setIsImportOPMLDialogOpen}