+14
-7
README.md
+14
-7
README.md
···
1
<div align="center">
2
<img src="./images/atbackup_large.png"/>
3
4
-
<h1>AT Backup</h1>
5
-
<p>One-click local Bluesky/ATProto backups</p>
6
-
</div>
7
8
## Built with
9
···
12
- ATProto
13
- atcute (for CAR file parsing)
14
- shadcn UI
15
-
16
-
## Recommended IDE Setup
17
-
18
-
- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
···
1
<div align="center">
2
<img src="./images/atbackup_large.png"/>
3
+
</div>
4
+
5
+
## Features
6
+
7
+
- Local first: saved to your file system
8
+
- Standard format: backups are stored as CAR files, which Bluesky uses
9
+
- Backup overview: see your backup's size and record types
10
+
11
+
## Contributing
12
+
13
+
We're welcome to any and all contributions. Mention us on Bluesky if we're slow, we may have missed your PR!
14
15
+
## Forking
16
+
17
+
You have our blessing and encouragement to fork this project and we're excited to see what you build!
18
19
## Built with
20
···
23
- ATProto
24
- atcute (for CAR file parsing)
25
- shadcn UI
docs/.yarn/install-state.gz
docs/.yarn/install-state.gz
This is a binary file and will not be displayed.
+19
-12
docs/app/auth/complete/page.tsx
+19
-12
docs/app/auth/complete/page.tsx
···
12
13
function AuthCompleteContent() {
14
const [loading, setLoading] = React.useState(true);
15
-
// Get all parameters from the URL
16
-
const currentUrl = new URL(window.location.href);
17
-
const params = new URLSearchParams(currentUrl.search);
18
19
-
params.forEach((value, key) => {
20
-
console.log(key, "=", value);
21
-
});
22
23
-
// Construct the redirect URL preserving all parameters
24
-
const redirectUrl = `atprotobackups://auth${
25
-
currentUrl.search || "?" + currentUrl.hash.slice(1)
26
-
}`;
27
-
useEffect(() => {
28
// Open the URL in the system's default handler and close the window after a short delay
29
-
window.location.href = redirectUrl;
30
31
// Close the window after a short delay to ensure the protocol handler is triggered
32
setTimeout(() => {
···
12
13
function AuthCompleteContent() {
14
const [loading, setLoading] = React.useState(true);
15
+
const [redirectUrl, setRedirectUrl] = React.useState("");
16
+
17
+
useEffect(() => {
18
+
// Only run on client side
19
+
if (typeof window === "undefined") return;
20
+
21
+
// Get all parameters from the URL
22
+
const currentUrl = new URL(window.location.href);
23
+
const params = new URLSearchParams(currentUrl.search);
24
+
25
+
params.forEach((value, key) => {
26
+
console.log(key, "=", value);
27
+
});
28
29
+
// Construct the redirect URL preserving all parameters
30
+
const url = `atprotobackups://auth${
31
+
currentUrl.search || "?" + currentUrl.hash.slice(1)
32
+
}`;
33
+
setRedirectUrl(url);
34
35
// Open the URL in the system's default handler and close the window after a short delay
36
+
window.location.href = url;
37
38
// Close the window after a short delay to ensure the protocol handler is triggered
39
setTimeout(() => {
+20
-15
docs/app/layout.tsx
+20
-15
docs/app/layout.tsx
···
6
import Image from "next/image";
7
import Link from "next/link";
8
import { Metadata } from "next";
9
10
export const metadata: Metadata = {
11
description: "One-click backup for Bluesky",
···
53
<Footer>
54
<div className="flex items-center justify-between w-full">
55
<span />
56
-
<Link
57
-
href="https://bsky.app/profile/atbackup.pages.dev"
58
-
className="hover:opacity-80 transition-opacity"
59
-
target="_blank"
60
-
rel="noopener noreferrer"
61
-
>
62
-
<Image
63
-
src="/bsky.svg"
64
-
alt="Bluesky"
65
-
width={24}
66
-
height={24}
67
-
color="white"
68
-
/>
69
-
</Link>
70
</div>
71
</Footer>
72
);
···
84
suppressHydrationWarning
85
>
86
<Head
87
-
// ... Your additional head options
88
>
89
{/* Your additional tags should be passed as `children` of `<Head>` element */}
90
</Head>
···
6
import Image from "next/image";
7
import Link from "next/link";
8
import { Metadata } from "next";
9
+
import { Bluesky, Tangled } from "@/components/icons";
10
11
export const metadata: Metadata = {
12
description: "One-click backup for Bluesky",
···
54
<Footer>
55
<div className="flex items-center justify-between w-full">
56
<span />
57
+
<div className="flex flex-row gap-2">
58
+
<Link
59
+
href="https://tangled.org/did:plc:5fzwpxt3rctfetyqpbigvgic/atbackup"
60
+
className="hover:opacity-70 transition-opacity"
61
+
target="_blank"
62
+
rel="noopener noreferrer"
63
+
>
64
+
<Tangled className="w-6 h-6 text-black dark:text-white" />
65
+
</Link>
66
+
<Link
67
+
href="https://bsky.app/profile/atbackup.pages.dev"
68
+
className="hover:opacity-70 transition-opacity"
69
+
target="_blank"
70
+
rel="noopener noreferrer"
71
+
>
72
+
<Bluesky className="w-6 h-6 text-black dark:text-white" />
73
+
</Link>
74
+
</div>
75
</div>
76
</Footer>
77
);
···
89
suppressHydrationWarning
90
>
91
<Head
92
+
// ... Your additional head options
93
>
94
{/* Your additional tags should be passed as `children` of `<Head>` element */}
95
</Head>
+78
-32
docs/app/page.tsx
+78
-32
docs/app/page.tsx
···
2
3
import Image from "next/image";
4
import React from "react";
5
-
import { Download, Pause, Play, RefreshCcw } from "lucide-react";
6
import { useThemeConfig } from "nextra-theme-docs";
7
import {
8
Accordion,
···
11
AccordionTrigger,
12
} from "@/components/ui/accordion";
13
14
function getOS(): "windows" | "macos" | "linux" | "unknown" {
15
if (typeof window === "undefined") return "unknown";
16
const ua = window.navigator.userAgent;
···
61
}/70`}
62
>
63
<div>
64
-
<h1 className="text-[2.5rem] font-bold text-white m-0 max-w-[350px] leading-tight">
65
One-click local backups of your atproto data
66
</h1>
67
-
<p className="text-lg text-white/80 mt-4 max-w-[350px]">
68
Easily back up your Bluesky posts, likes, and other records (e.g.
69
other AT Protocol app data) to your computer's filesystem.
70
</p>
71
<a
72
href={url}
73
-
className="mt-6 px-6 py-3 bg-white text-black rounded-md hover:bg-white/80 transition-colors inline-block"
74
download
75
>
76
<div className="flex items-center gap-2 font-medium">
···
91
</div>
92
</div>
93
<div className="w-full h-[0.5px] bg-white/10 mb-4" />
94
<div className="flex flex-col items-center max-w[800px] mx-auto my-16 px-4 w-full">
95
<Accordion
96
type="single"
97
collapsible
98
className="w-full max-w-2xl flex flex-col gap-4"
99
>
100
-
<AccordionItem value="item-1">
101
-
<AccordionTrigger className="flex items-center justify-between gap-2 text-lg font-medium bg-white/5 rounded-md px-4 py-3 cursor-pointer hover:no-underline hover:bg-white/8 transition">
102
<div className="flex items-center gap-4">
103
<RefreshCcw size={20} />
104
<span className="text-left">Unified backup format</span>
105
</div>
106
<span className="ml-auto" />
107
</AccordionTrigger>
108
-
<AccordionContent className="mt-2 text-gray-300 text-base rounded-md p-4">
109
Your data is saved as a CAR file, which Bluesky uses, and blobs
110
-
are stored as their original files. This ensures you can restore
111
-
your data in the future by yourself.
112
</AccordionContent>
113
</AccordionItem>
114
-
<AccordionItem value="item-2">
115
-
<AccordionTrigger className="flex items-center justify-between gap-2 text-lg font-medium bg-white/5 rounded-md px-4 py-3 cursor-pointer hover:no-underline hover:bg-white/8 transition">
116
<div className="flex items-center gap-4">
117
-
<RefreshCcw size={20} />
118
-
<span className="text-left">Unified backup format</span>
119
</div>
120
<span className="ml-auto" />
121
</AccordionTrigger>
122
-
<AccordionContent className="mt-2 text-gray-300 text-base rounded-md p-4">
123
-
Your data is saved as a CAR file, which Bluesky uses, and blobs
124
-
are stored as their original files. This ensures you can restore
125
-
your data in the future by yourself.
126
</AccordionContent>
127
</AccordionItem>
128
</Accordion>
129
-
</div>
130
-
<div className="flex flex-col items-center w-full">
131
-
<div className="flex flex-col md:flex-row items-center justify-center gap-8 min-h-[60vh] p-8">
132
-
<div>
133
-
<VideoPlayer className="w-lg" />
134
-
</div>
135
-
<div className="relative mt-8 md:mt-0">
136
-
<h1 className="text-[2.5rem] font-bold text-white m-0 max-w-[350px] leading-tight">
137
-
Intuitive and cozy
138
-
</h1>
139
-
<p className="text-lg text-white/80 mt-4 max-w-[350px]">
140
-
See how easy it is to save your Bluesky data to your computer.
141
-
</p>
142
-
</div>
143
-
</div>
144
</div>
145
</div>
146
);
···
2
3
import Image from "next/image";
4
import React from "react";
5
+
import {
6
+
CloudOff,
7
+
Download,
8
+
FolderGit2,
9
+
Pause,
10
+
Play,
11
+
RefreshCcw,
12
+
} from "lucide-react";
13
import { useThemeConfig } from "nextra-theme-docs";
14
import {
15
Accordion,
···
18
AccordionTrigger,
19
} from "@/components/ui/accordion";
20
21
+
// Accordion styling constants
22
+
const ACCORDION_TRIGGER_CLASSES =
23
+
"flex items-center justify-between gap-2 text-lg font-medium bg-black/5 dark:bg-white/5 rounded-md px-4 py-3 cursor-pointer hover:no-underline hover:bg-black/8 dark:hover:bg-white/8 transition";
24
+
const ACCORDION_CONTENT_CLASSES =
25
+
"mt-2 text-black/75 dark:text-white/75 text-base rounded-md p-4";
26
+
27
function getOS(): "windows" | "macos" | "linux" | "unknown" {
28
if (typeof window === "undefined") return "unknown";
29
const ua = window.navigator.userAgent;
···
74
}/70`}
75
>
76
<div>
77
+
<h1 className="text-[2.5rem] font-bold text-black dark:text-white m-0 max-w-[350px] leading-tight">
78
One-click local backups of your atproto data
79
</h1>
80
+
<p className="text-lg text-black/80 dark:text-white/80 mt-4 max-w-[350px]">
81
Easily back up your Bluesky posts, likes, and other records (e.g.
82
other AT Protocol app data) to your computer's filesystem.
83
</p>
84
<a
85
href={url}
86
+
className="mt-6 px-6 py-3 dark:bg-white bg-black dark:text-black text-white rounded-md hover:bg-black/80 dark:hover:bg-white/80 transition-colors inline-block"
87
download
88
>
89
<div className="flex items-center gap-2 font-medium">
···
104
</div>
105
</div>
106
<div className="w-full h-[0.5px] bg-white/10 mb-4" />
107
+
108
+
<div className="flex flex-col items-center w-full">
109
+
<div className="flex flex-col md:flex-row items-center justify-center gap-8 min-h-[60vh] p-8">
110
+
<div>
111
+
<VideoPlayer className="w-lg" />
112
+
</div>
113
+
<div className="relative mt-8 md:mt-0">
114
+
<h1 className="text-[2.5rem] font-bold text-black dark:text-white m-0 max-w-[350px] leading-tight">
115
+
Intuitive and cozy
116
+
</h1>
117
+
<p className="text-lg text-black/80 dark:text-white/80 mt-4 max-w-[350px]">
118
+
See how easy it is to save your Bluesky data to your computer.
119
+
</p>
120
+
</div>
121
+
</div>
122
+
</div>
123
<div className="flex flex-col items-center max-w[800px] mx-auto my-16 px-4 w-full">
124
<Accordion
125
type="single"
126
collapsible
127
className="w-full max-w-2xl flex flex-col gap-4"
128
>
129
+
<AccordionItem value="item-1" className="border-none">
130
+
<AccordionTrigger className={ACCORDION_TRIGGER_CLASSES}>
131
<div className="flex items-center gap-4">
132
<RefreshCcw size={20} />
133
<span className="text-left">Unified backup format</span>
134
</div>
135
<span className="ml-auto" />
136
</AccordionTrigger>
137
+
<AccordionContent className={ACCORDION_CONTENT_CLASSES}>
138
Your data is saved as a CAR file, which Bluesky uses, and blobs
139
+
are stored as their original format (in blob files). This ensures
140
+
you can restore your data in the future by yourself.
141
</AccordionContent>
142
</AccordionItem>
143
+
<AccordionItem value="item-2" className="border-none">
144
+
<AccordionTrigger className={ACCORDION_TRIGGER_CLASSES}>
145
<div className="flex items-center gap-4">
146
+
<CloudOff size={20} />
147
+
<span className="text-left">Local only</span>
148
</div>
149
<span className="ml-auto" />
150
</AccordionTrigger>
151
+
<AccordionContent className={ACCORDION_CONTENT_CLASSES}>
152
+
Your backups are saved directly to your computer's file system, in
153
+
documents, ensuring you always have access. If you prefer cloud
154
+
storage, you can tools like{" "}
155
+
<a
156
+
href="https://bsky.storage"
157
+
className="text-blue-500 underline"
158
+
>
159
+
Storacha
160
+
</a>.
161
+
</AccordionContent>
162
+
</AccordionItem>
163
+
<AccordionItem value="item-3">
164
+
<AccordionTrigger className={ACCORDION_TRIGGER_CLASSES}>
165
+
<div className="flex items-center gap-4">
166
+
<FolderGit2 size={20} />
167
+
<span className="text-left">Open-source</span>
168
+
</div>
169
+
<span className="ml-auto" />
170
+
</AccordionTrigger>
171
+
<AccordionContent className={ACCORDION_CONTENT_CLASSES}>
172
+
We're completly open-source, star us on{" "}
173
+
<a
174
+
href="https://github.com/Turtlepaw/atproto-backup"
175
+
className="text-blue-500 underline"
176
+
>
177
+
GitHub
178
+
</a>{" "}
179
+
or{" "}
180
+
<a
181
+
href="https://tangled.org/did:plc:5fzwpxt3rctfetyqpbigvgic/atbackup"
182
+
className="text-blue-500 underline"
183
+
>
184
+
Tangled
185
+
</a>. We're also happy to merge your pull request! (mention us on
186
+
Bluesky if we're a little slow)
187
</AccordionContent>
188
</AccordionItem>
189
</Accordion>
190
</div>
191
</div>
192
);
+42
docs/components/icons.tsx
+42
docs/components/icons.tsx
···
···
1
+
export function Tangled(props: React.SVGProps<SVGSVGElement>) {
2
+
return (
3
+
<svg
4
+
version="1.1"
5
+
id="svg1"
6
+
width="25"
7
+
height="25"
8
+
viewBox="0 0 25 25"
9
+
xmlns="http://www.w3.org/2000/svg"
10
+
{...props}
11
+
>
12
+
<title>Dolly</title>
13
+
<defs id="defs1"></defs>
14
+
15
+
<g id="g1">
16
+
<path
17
+
fill="currentColor"
18
+
style={{ strokeWidth: 0.111183 }}
19
+
d="m 16.348974,24.09935 -0.06485,-0.03766 -0.202005,-0.0106 -0.202008,-0.01048 -0.275736,-0.02601 -0.275734,-0.02602 v -0.02649 -0.02648 l -0.204577,-0.04019 -0.204578,-0.04019 -0.167616,-0.08035 -0.167617,-0.08035 -0.0014,-0.04137 -0.0014,-0.04137 -0.266473,-0.143735 -0.266475,-0.143735 -0.276098,-0.20335 -0.2761,-0.203347 -0.262064,-0.251949 -0.262064,-0.25195 -0.22095,-0.284628 -0.220948,-0.284629 -0.170253,-0.284631 -0.170252,-0.284628 -0.01341,-0.0144 -0.0134,-0.0144 -0.141982,0.161297 -0.14198,0.1613 -0.22313,0.21426 -0.223132,0.214264 -0.186025,0.146053 -0.186023,0.14605 -0.252501,0.163342 -0.252502,0.163342 -0.249014,0.115348 -0.249013,0.115336 0.0053,0.03241 0.0053,0.03241 -0.1716725,0.04599 -0.171669,0.046 -0.3379966,0.101058 -0.3379972,0.101058 -0.1778925,0.04506 -0.1778935,0.04508 -0.3913655,0.02601 -0.3913643,0.02603 -0.3557868,-0.03514 -0.3557863,-0.03514 -0.037426,-0.03029 -0.037427,-0.03029 -0.076924,0.02011 -0.076924,0.02011 -0.050508,-0.05051 -0.050405,-0.05056 L 6.6604532,23.110188 6.451745,23.063961 6.1546135,22.960559 5.8574835,22.857156 5.5319879,22.694039 5.2064938,22.530922 4.8793922,22.302961 4.5522905,22.075005 4.247598,21.786585 3.9429055,21.49817 3.7185335,21.208777 3.4941628,20.919385 3.3669822,20.705914 3.239803,20.492443 3.1335213,20.278969 3.0272397,20.065499 2.9015252,19.7275 2.7758105,19.389504 2.6925225,18.998139 2.6092345,18.606774 2.6096814,17.91299 2.6101284,17.219208 2.6744634,16.90029 2.7387984,16.581374 2.8474286,16.242088 2.9560588,15.9028 3.1137374,15.583492 3.2714148,15.264182 3.3415068,15.150766 3.4115988,15.03735 3.3127798,14.96945 3.2139618,14.90157 3.0360685,14.800239 2.8581753,14.698908 2.5913347,14.503228 2.3244955,14.307547 2.0621238,14.055599 1.7997507,13.803651 1.6111953,13.56878 1.4226411,13.333906 1.2632237,13.087474 1.1038089,12.841042 0.97442,12.575195 0.8450307,12.30935 0.724603,11.971351 0.6041766,11.633356 0.52150365,11.241991 0.4388285,10.850626 0.44091592,10.156842 0.44300333,9.4630594 0.54235911,9.0369608 0.6417149,8.6108622 0.7741173,8.2694368 0.9065196,7.9280115 1.0736303,7.6214262 1.2407515,7.3148397 1.45931,7.0191718 1.6778685,6.7235039 1.9300326,6.4611321 2.1821966,6.1987592 2.4134579,6.0137228 2.6447193,5.8286865 2.8759792,5.6776409 3.1072406,5.526594 3.4282004,5.3713977 3.7491603,5.2162016 3.9263009,5.1508695 4.1034416,5.0855373 4.2813348,4.7481598 4.4592292,4.4107823 4.6718,4.108422 4.8843733,3.8060618 5.198353,3.4805372 5.5123313,3.155014 5.7685095,2.9596425 6.0246877,2.7642722 6.329187,2.5851365 6.6336863,2.406002 6.9497657,2.2751596 7.2658453,2.1443184 7.4756394,2.0772947 7.6854348,2.01027 8.0825241,1.931086 8.4796139,1.851902 l 0.5870477,0.00291 0.5870469,0.00291 0.4447315,0.092455 0.444734,0.092455 0.302419,0.1105495 0.302417,0.1105495 0.329929,0.1646046 0.32993,0.1646033 0.239329,-0.2316919 0.239329,-0.2316919 0.160103,-0.1256767 0.160105,-0.1256767 0.160102,-0.1021909 0.160105,-0.1021899 0.142315,-0.082328 0.142314,-0.082328 0.231262,-0.1090091 0.231259,-0.1090091 0.26684,-0.098743 0.266839,-0.098743 0.320208,-0.073514 0.320209,-0.073527 0.355787,-0.041833 0.355785,-0.041834 0.426942,0.023827 0.426945,0.023828 0.355785,0.071179 0.355788,0.0711791 0.284627,0.09267 0.284629,0.09267 0.28514,0.1310267 0.28514,0.1310255 0.238179,0.1446969 0.238174,0.1446979 0.259413,0.1955332 0.259413,0.1955319 0.290757,0.296774 0.290758,0.2967753 0.151736,0.1941581 0.151734,0.1941594 0.135326,0.2149951 0.135327,0.2149952 0.154755,0.3202073 0.154758,0.3202085 0.09409,0.2677358 0.09409,0.267737 0.06948,0.3319087 0.06948,0.3319099 0.01111,0.00808 0.01111,0.00808 0.444734,0.2173653 0.444734,0.2173665 0.309499,0.2161102 0.309497,0.2161101 0.309694,0.2930023 0.309694,0.2930037 0.18752,0.2348726 0.187524,0.2348727 0.166516,0.2574092 0.166519,0.2574108 0.15273,0.3260252 0.152734,0.3260262 0.08972,0.2668403 0.08971,0.2668391 0.08295,0.3913655 0.08295,0.3913652 -6.21e-4,0.6582049 -6.21e-4,0.658204 -0.06362,0.315725 -0.06362,0.315725 -0.09046,0.289112 -0.09046,0.289112 -0.122759,0.281358 -0.12276,0.281356 -0.146626,0.252323 -0.146629,0.252322 -0.190443,0.258668 -0.190448,0.258671 -0.254911,0.268356 -0.254911,0.268355 -0.286872,0.223127 -0.286874,0.223127 -0.320203,0.187693 -0.320209,0.187693 -0.04347,0.03519 -0.04347,0.03521 0.0564,0.12989 0.0564,0.129892 0.08728,0.213472 0.08728,0.213471 0.189755,0.729363 0.189753,0.729362 0.0652,0.302417 0.0652,0.302419 -0.0018,0.675994 -0.0018,0.675995 -0.0801,0.373573 -0.08009,0.373577 -0.09,0.266839 -0.09,0.26684 -0.190389,0.391364 -0.19039,0.391366 -0.223169,0.320207 -0.223167,0.320209 -0.303585,0.315294 -0.303584,0.315291 -0.284631,0.220665 -0.284629,0.220663 -0.220128,0.132359 -0.220127,0.132358 -0.242395,0.106698 -0.242394,0.106699 -0.08895,0.04734 -0.08895,0.04733 -0.249052,0.07247 -0.24905,0.07247 -0.322042,0.0574 -0.322044,0.0574 -0.282794,-0.003 -0.282795,-0.003 -0.07115,-0.0031 -0.07115,-0.0031 -0.177894,-0.0033 -0.177893,-0.0033 -0.124528,0.02555 -0.124528,0.02555 z m -4.470079,-5.349839 0.214838,-0.01739 0.206601,-0.06782 0.206602,-0.06782 0.244389,-0.117874 0.244393,-0.11786 0.274473,-0.206822 0.27447,-0.20682 0.229308,-0.257201 0.229306,-0.2572 0.219161,-0.28463 0.219159,-0.284629 0.188541,-0.284628 0.188543,-0.28463 0.214594,-0.373574 0.214593,-0.373577 0.133861,-0.312006 0.133865,-0.312007 0.02861,-0.01769 0.02861,-0.01769 0.197275,0.26212 0.197278,0.262119 0.163613,0.150814 0.163614,0.150814 0.201914,0.09276 0.201914,0.09276 0.302417,0.01421 0.302418,0.01421 0.213472,-0.08025 0.213471,-0.08025 0.200606,-0.204641 0.200606,-0.204642 0.09242,-0.278887 0.09241,-0.278888 0.05765,-0.302418 0.05764,-0.302416 L 18.41327,13.768114 18.39502,13.34117 18.31849,12.915185 18.24196,12.4892 18.15595,12.168033 18.06994,11.846867 17.928869,11.444534 17.787801,11.042201 17.621278,10.73296 17.454757,10.423723 17.337388,10.263619 17.220021,10.103516 17.095645,9.9837986 16.971268,9.8640816 16.990048,9.6813736 17.008828,9.4986654 16.947568,9.249616 16.886308,9.0005655 16.752419,8.7159355 16.618521,8.4313217 16.435707,8.2294676 16.252892,8.0276114 16.079629,7.9004245 15.906366,7.773238 l -0.20429,0.1230127 -0.204289,0.1230121 -0.26702,0.059413 -0.267022,0.059413 -0.205761,-0.021508 -0.205766,-0.021508 -0.23495,-0.08844 -0.234953,-0.08844 -0.118429,-0.090334 -0.118428,-0.090333 h -0.03944 -0.03944 L 13.711268,7.8540732 13.655958,7.9706205 13.497227,8.1520709 13.338499,8.3335203 13.168394,8.4419112 12.998289,8.550301 12.777045,8.624223 12.5558,8.698155 H 12.275611 11.995429 L 11.799973,8.6309015 11.604513,8.5636472 11.491311,8.5051061 11.37811,8.446565 11.138172,8.2254579 10.898231,8.0043497 l -0.09565,-0.084618 -0.09565,-0.084613 -0.218822,0.198024 -0.218822,0.1980231 -0.165392,0.078387 -0.1653925,0.078387 -0.177894,0.047948 -0.177892,0.047948 L 9.3635263,8.4842631 9.144328,8.4846889 8.9195029,8.4147138 8.6946778,8.3447386 8.5931214,8.4414036 8.491565,8.5380686 8.3707618,8.7019598 8.2499597,8.8658478 8.0802403,8.9290726 7.9105231,8.9922974 7.7952769,9.0780061 7.6800299,9.1637148 7.5706169,9.2778257 7.4612038,9.3919481 7.1059768,9.9205267 6.7507497,10.449105 l -0.2159851,0.449834 -0.2159839,0.449834 -0.2216572,0.462522 -0.2216559,0.462523 -0.1459343,0.337996 -0.1459342,0.337998 -0.055483,0.220042 -0.055483,0.220041 -0.015885,0.206903 -0.015872,0.206901 0.034307,0.242939 0.034307,0.24294 0.096281,0.196632 0.096281,0.196634 0.143607,0.125222 0.1436071,0.125222 0.1873143,0.08737 0.1873141,0.08737 0.2752084,0.002 0.2752084,0.002 0.2312297,-0.09773 0.231231,-0.09772 0.1067615,-0.07603 0.1067614,-0.07603 0.3679062,-0.29377 0.3679065,-0.293771 0.026804,0.01656 0.026804,0.01656 0.023626,0.466819 0.023626,0.466815 0.088326,0.513195 0.088326,0.513193 0.08897,0.364413 0.08897,0.364411 0.1315362,0.302418 0.1315352,0.302418 0.1051964,0.160105 0.1051954,0.160103 0.1104741,0.11877 0.1104731,0.118769 0.2846284,0.205644 0.2846305,0.205642 0.144448,0.07312 0.144448,0.07312 0.214787,0.05566 0.214787,0.05566 0.245601,0.03075 0.245602,0.03075 0.204577,-0.0125 0.204578,-0.0125 z m 0.686342,-3.497495 -0.11281,-0.06077 -0.106155,-0.134033 -0.106155,-0.134031 -0.04406,-0.18371 -0.04406,-0.183707 0.02417,-0.553937 0.02417,-0.553936 0.03513,-0.426945 0.03513,-0.426942 0.07225,-0.373576 0.07225,-0.373575 0.05417,-0.211338 0.05417,-0.211339 0.0674,-0.132112 0.0674,-0.132112 0.132437,-0.10916 0.132437,-0.109161 0.187436,-0.04195 0.187438,-0.04195 0.170366,0.06469 0.170364,0.06469 0.114312,0.124073 0.114313,0.124086 0.04139,0.18495 0.04139,0.184951 -0.111218,0.459845 -0.111219,0.459844 -0.03383,0.26584 -0.03382,0.265841 -0.03986,0.818307 -0.03986,0.818309 -0.0378,0.15162 -0.03779,0.151621 -0.11089,0.110562 -0.110891,0.110561 -0.114489,0.04913 -0.114489,0.04913 -0.187932,-0.0016 -0.187929,-0.0016 z m -2.8087655,-0.358124 -0.146445,-0.06848 -0.088025,-0.119502 -0.088024,-0.119502 -0.038581,-0.106736 -0.038581,-0.106736 -0.02237,-0.134956 -0.02239,-0.134957 -0.031955,-0.46988 -0.031955,-0.469881 0.036203,-0.444733 0.036203,-0.444731 0.048862,-0.215257 0.048862,-0.215255 0.076082,-0.203349 0.076081,-0.203348 0.0936,-0.111244 0.0936,-0.111245 0.143787,-0.06531 0.1437865,-0.06532 h 0.142315 0.142314 l 0.142314,0.06588 0.142316,0.06588 0.093,0.102325 0.093,0.102325 0.04042,0.120942 0.04042,0.120942 v 0.152479 0.152477 l -0.03347,0.08804 -0.03347,0.08805 -0.05693,0.275653 -0.05693,0.275651 2.11e-4,0.430246 2.12e-4,0.430243 0.04294,0.392646 0.04295,0.392647 -0.09189,0.200702 -0.09189,0.200702 -0.148688,0.0984 -0.148687,0.0984 -0.20136,0.01212 -0.2013595,0.01212 z"
20
+
id="path4"
21
+
>
22
+
</path>
23
+
</g>
24
+
</svg>
25
+
);
26
+
}
27
+
export function Bluesky(props: React.SVGProps<SVGSVGElement>) {
28
+
return (
29
+
<svg
30
+
role="img"
31
+
viewBox="0 0 24 24"
32
+
xmlns="http://www.w3.org/2000/svg"
33
+
{...props}
34
+
>
35
+
<title>Bluesky</title>
36
+
<path
37
+
d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.136-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.953 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z"
38
+
fill="currentColor"
39
+
/>
40
+
</svg>
41
+
);
42
+
}
+2
-1
docs/package.json
+2
-1
docs/package.json
+21
docs/yarn.lock
+21
docs/yarn.lock
···
7139
tailwind-merge: "npm:^3.3.1"
7140
tailwindcss: "npm:^4.1.11"
7141
tw-animate-css: "npm:^1.3.8"
7142
languageName: unknown
7143
linkType: soft
7144
···
7924
media-typer: "npm:^1.1.0"
7925
mime-types: "npm:^3.0.0"
7926
checksum: 10c0/7f7ec0a060b16880bdad36824ab37c26019454b67d73e8a465ed5a3587440fbe158bc765f0da68344498235c877e7dbbb1600beccc94628ed05599d667951b99
7927
languageName: node
7928
linkType: hard
7929
···
7139
tailwind-merge: "npm:^3.3.1"
7140
tailwindcss: "npm:^4.1.11"
7141
tw-animate-css: "npm:^1.3.8"
7142
+
typescript: "npm:^5.9.2"
7143
languageName: unknown
7144
linkType: soft
7145
···
7925
media-typer: "npm:^1.1.0"
7926
mime-types: "npm:^3.0.0"
7927
checksum: 10c0/7f7ec0a060b16880bdad36824ab37c26019454b67d73e8a465ed5a3587440fbe158bc765f0da68344498235c877e7dbbb1600beccc94628ed05599d667951b99
7928
+
languageName: node
7929
+
linkType: hard
7930
+
7931
+
"typescript@npm:^5.9.2":
7932
+
version: 5.9.2
7933
+
resolution: "typescript@npm:5.9.2"
7934
+
bin:
7935
+
tsc: bin/tsc
7936
+
tsserver: bin/tsserver
7937
+
checksum: 10c0/cd635d50f02d6cf98ed42de2f76289701c1ec587a363369255f01ed15aaf22be0813226bff3c53e99d971f9b540e0b3cc7583dbe05faded49b1b0bed2f638a18
7938
+
languageName: node
7939
+
linkType: hard
7940
+
7941
+
"typescript@patch:typescript@npm%3A^5.9.2#optional!builtin<compat/typescript>":
7942
+
version: 5.9.2
7943
+
resolution: "typescript@patch:typescript@npm%3A5.9.2#optional!builtin<compat/typescript>::version=5.9.2&hash=5786d5"
7944
+
bin:
7945
+
tsc: bin/tsc
7946
+
tsserver: bin/tsserver
7947
+
checksum: 10c0/34d2a8e23eb8e0d1875072064d5e1d9c102e0bdce56a10a25c0b917b8aa9001a9cf5c225df12497e99da107dc379360bc138163c66b55b95f5b105b50578067e
7948
languageName: node
7949
linkType: hard
7950