this repo has no description
1<script lang="ts">
2 import { _ } from '../lib/i18n'
3 import { getAuthState } from '../lib/auth.svelte'
4 const auth = getAuthState()
5</script>
6<div class="home">
7 <header class="hero">
8 <h1>Tranquil PDS</h1>
9 <p class="tagline">A Personal Data Server for the AT Protocol</p>
10 </header>
11 <section>
12 <h2>What is a PDS?</h2>
13 <p>
14 Bluesky runs on a federated protocol called AT Protocol. Your account lives on a PDS,
15 a server that stores your posts, profile, follows, and cryptographic keys. Bluesky hosts
16 one for you at bsky.social, but you can run your own. Self-hosting means you control your
17 data; you're not dependent on any company's servers, and your account + data is actually yours.
18 </p>
19 </section>
20 <section>
21 <h2>What's different about Tranquil?</h2>
22 <p>
23 This software isn't an afterthought by a company with limited resources.
24 It is a superset of the reference PDS, including:
25 </p>
26 <ul>
27 <li>Passkeys and 2FA (WebAuthn/FIDO2, TOTP, backup codes, trusted devices)</li>
28 <li>did:web support (PDS-hosted subdomains or bring-your-own)</li>
29 <li>Multi-channel notifications (email, discord, telegram, signal)</li>
30 <li>Granular OAuth scopes with a consent UI</li>
31 <li>Built-in web UI for account management, repo browsing, and admin</li>
32 </ul>
33 <p>
34 Full compatibility with Bluesky's reference PDS: same endpoints, same behavior,
35 same client compatibility. Everything works.
36 </p>
37 </section>
38 <div class="cta">
39 {#if auth.session}
40 <a href="#/dashboard" class="btn">@{auth.session.handle}</a>
41 {:else}
42 <a href="#/login" class="btn">{$_('login.button')}</a>
43 <a href="#/register" class="btn secondary">{$_('login.createAccount')}</a>
44 {/if}
45 </div>
46 <footer>
47 <a href="https://tangled.org/lewis.moe/bspds-sandbox" target="_blank" rel="noopener">Source code</a>
48 </footer>
49</div>
50<style>
51 .home {
52 max-width: var(--width-md);
53 margin: 0 auto;
54 padding: var(--space-7);
55 }
56
57 .hero {
58 text-align: center;
59 margin-bottom: var(--space-8);
60 padding-top: var(--space-7);
61 }
62
63 .hero h1 {
64 font-size: var(--text-4xl);
65 margin-bottom: var(--space-3);
66 }
67
68 .tagline {
69 color: var(--text-secondary);
70 font-size: var(--text-xl);
71 }
72
73 section {
74 margin-bottom: var(--space-7);
75 }
76
77 h2 {
78 margin-bottom: var(--space-4);
79 }
80
81 p {
82 color: var(--text-secondary);
83 margin-bottom: var(--space-4);
84 }
85
86 ul {
87 color: var(--text-secondary);
88 margin: 0 0 var(--space-4) 0;
89 padding-left: var(--space-6);
90 line-height: var(--leading-relaxed);
91 }
92
93 li {
94 margin-bottom: var(--space-2);
95 }
96
97 .cta {
98 display: flex;
99 gap: var(--space-4);
100 justify-content: center;
101 margin: var(--space-8) 0;
102 }
103
104 .btn {
105 display: inline-block;
106 padding: var(--space-4) var(--space-7);
107 border-radius: var(--radius-md);
108 font-size: var(--text-base);
109 font-weight: var(--font-medium);
110 text-decoration: none;
111 transition: background var(--transition-normal), border-color var(--transition-normal);
112 background: var(--accent);
113 color: var(--text-inverse);
114 }
115
116 .btn:hover {
117 background: var(--accent-hover);
118 text-decoration: none;
119 }
120
121 .btn.secondary {
122 background: transparent;
123 color: var(--accent);
124 border: 1px solid var(--accent);
125 }
126
127 .btn.secondary:hover {
128 background: var(--accent);
129 color: var(--text-inverse);
130 }
131
132 footer {
133 text-align: center;
134 padding-top: var(--space-7);
135 border-top: 1px solid var(--border-color);
136 }
137
138 footer a {
139 color: var(--text-muted);
140 font-size: var(--text-sm);
141 }
142
143 footer a:hover {
144 color: var(--accent);
145 }
146</style>