include links and such
+88
-20
src/templates.rs
+88
-20
src/templates.rs
···
9
9
10
10
11
11
12
+
<meta property="og:type" content="website">
13
+
<meta property="og:url" content="https://at-me.fly.dev/">
14
+
<meta property="og:title" content="@me - explore your atproto identity">
15
+
<meta property="og:description" content="visualize your decentralized identity and see what apps have stored data in your Personal Data Server">
16
+
<meta property="og:image" content="https://at-me.fly.dev/static/og-image.png">
12
17
18
+
<!-- Twitter -->
19
+
<meta property="twitter:card" content="summary_large_image">
20
+
<meta property="twitter:url" content="https://at-me.fly.dev/">
21
+
<meta property="twitter:title" content="@me - explore your atproto identity">
22
+
<meta property="twitter:description" content="visualize your decentralized identity and see what apps have stored data in your Personal Data Server">
23
+
<meta property="twitter:image" content="https://at-me.fly.dev/static/og-image.png">
13
24
25
+
<style>
14
26
15
27
16
28
···
215
227
216
228
217
229
230
+
<meta property="og:type" content="website">
231
+
<meta property="og:url" content="https://at-me.fly.dev/">
232
+
<meta property="og:title" content="@me - explore your atproto identity">
233
+
<meta property="og:description" content="visualize your decentralized identity and see what apps have stored data in your Personal Data Server">
234
+
<meta property="og:image" content="https://at-me.fly.dev/static/og-image.png">
218
235
236
+
<!-- Twitter -->
237
+
<meta property="twitter:card" content="summary_large_image">
238
+
<meta property="twitter:url" content="https://at-me.fly.dev/">
239
+
<meta property="twitter:title" content="@me - explore your atproto identity">
240
+
<meta property="twitter:description" content="visualize your decentralized identity and see what apps have stored data in your Personal Data Server">
241
+
<meta property="twitter:image" content="https://at-me.fly.dev/static/og-image.png">
219
242
243
+
<style>
220
244
221
245
222
246
···
851
875
852
876
853
877
878
+
.onboarding-progress span.done {{
879
+
background: var(--text-light);
880
+
}}
854
881
882
+
.stats-box {{
883
+
display: flex;
884
+
gap: 1.5rem;
885
+
margin: 1.5rem 0;
886
+
padding: 1rem;
887
+
background: var(--bg);
888
+
border-radius: 4px;
889
+
border: 1px solid var(--border);
890
+
}}
855
891
892
+
.stat {{
893
+
flex: 1;
894
+
text-align: center;
895
+
}}
856
896
897
+
.stat-value {{
898
+
font-size: 1.8rem;
899
+
font-weight: 600;
900
+
color: var(--text);
901
+
margin-bottom: 0.25rem;
902
+
}}
857
903
904
+
.stat-label {{
905
+
font-size: 0.65rem;
906
+
color: var(--text-light);
907
+
text-transform: uppercase;
908
+
letter-spacing: 0.05em;
909
+
}}
858
910
911
+
.ownership-box {{
912
+
margin: 1rem 0;
913
+
padding: 1rem;
914
+
background: var(--bg);
915
+
border-radius: 4px;
916
+
border: 1px solid var(--border);
917
+
}}
859
918
919
+
.ownership-box.yours {{
920
+
background: rgba(76, 175, 80, 0.05);
921
+
border-color: rgba(76, 175, 80, 0.3);
922
+
}}
860
923
924
+
@media (prefers-color-scheme: dark) {{
925
+
.ownership-box.yours {{
926
+
background: rgba(76, 175, 80, 0.08);
927
+
border-color: rgba(76, 175, 80, 0.4);
928
+
}}
929
+
}}
861
930
931
+
.ownership-header {{
932
+
font-size: 0.7rem;
933
+
font-weight: 600;
934
+
color: var(--text);
935
+
margin-bottom: 0.5rem;
936
+
text-transform: uppercase;
937
+
letter-spacing: 0.05em;
938
+
}}
862
939
940
+
.ownership-text {{
941
+
font-size: 0.7rem;
942
+
color: var(--text-lighter);
943
+
line-height: 1.5;
944
+
}}
863
945
864
-
865
-
866
-
867
-
868
-
869
-
870
-
871
-
872
-
873
-
874
-
875
-
876
-
877
-
878
-
.onboarding-progress span.done {{
879
-
background: var(--text-light);
946
+
.ownership-text strong {{
947
+
color: var(--text);
880
948
}}
881
949
</style>
882
950
</head>
···
886
954
887
955
<div class="overlay" id="overlay"></div>
888
956
<div class="info-modal" id="infoModal">
889
-
<h2>@me - your at protocol identity</h2>
890
-
<p>in decentralized social networks, you own your identity and your data lives in your personal data server (pds).</p>
891
-
<p>third-party applications create records in your repository using different lexicons (data schemas). for example, bluesky creates posts, white wind stores blog entries, tangled.org hosts code repositories, and frontpage aggregates links - all in the same place.</p>
892
-
<p>this visualization shows your identity at the center, surrounded by the third-party apps that have created data for you. click an app to see what types of records it stores, then click a record type to see the actual data.</p>
957
+
<h2>@me - your repository</h2>
958
+
<p>on traditional social platforms, your content is locked in. want to switch? you start from zero. you build their network, they control the distribution.</p>
959
+
<p>on atproto, you own everything. your data lives in your <a href="https://atproto.com/guides/overview" target="_blank" rel="noopener noreferrer" style="color: var(--text); text-decoration: underline;">Personal Data Server (PDS)</a>. apps like bluesky, whitewind, and frontpage just write to YOUR space. switch apps anytime, take it all with you.</p>
960
+
<p>click your @ in the center to see what you've built. click any app to see what it's stored in your repository.</p>
893
961
<button id="closeInfo">got it</button>
894
962
<button id="restartTour" onclick="window.restartOnboarding()" style="margin-left: 0.5rem; background: var(--surface-hover);">restart tour</button>
895
963
</div>
+66
-31
static/app.js
+66
-31
static/app.js
···
93
93
// User may not have an avatar set
94
94
});
95
95
96
-
// Add identity click handler to show PDS info
96
+
// Store collections and apps for later use
97
+
let allCollections = [];
98
+
let apps = {};
99
+
100
+
// Get all collections from PDS
101
+
return fetch(`${pds}/xrpc/com.atproto.repo.describeRepo?repo=${did}`);
102
+
})
103
+
.then(r => r.json())
104
+
.then(repo => {
105
+
const collections = repo.collections || [];
106
+
allCollections = collections;
107
+
108
+
// Group by app namespace (first two parts of lexicon)
109
+
apps = {};
110
+
collections.forEach(collection => {
111
+
const parts = collection.split('.');
112
+
if (parts.length >= 2) {
113
+
const namespace = `${parts[0]}.${parts[1]}`;
114
+
if (!apps[namespace]) apps[namespace] = [];
115
+
apps[namespace].push(collection);
116
+
}
117
+
});
118
+
119
+
// Add identity click handler now that we have the data
120
+
const pdsHost = globalPds.replace('https://', '').replace('http://', '');
97
121
document.querySelector('.identity').addEventListener('click', () => {
98
122
const detail = document.getElementById('detail');
99
-
const pdsHost = pds.replace('https://', '').replace('http://', '');
123
+
const appCount = Object.keys(apps).length;
124
+
100
125
detail.innerHTML = `
101
126
<button class="detail-close" id="detailClose">×</button>
102
-
<h3>your identity</h3>
103
-
<div class="subtitle">decentralized identifier & storage</div>
104
-
<div class="tree-item">
105
-
<div class="tree-item-header">
106
-
<span style="color: var(--text-light);">did</span>
107
-
<span style="font-size: 0.6rem; color: var(--text);">${did}</span>
127
+
<h3>your repository</h3>
128
+
<div class="subtitle">what you've built</div>
129
+
130
+
<div class="stats-box">
131
+
<div class="stat">
132
+
<div class="stat-value">${allCollections.length}</div>
133
+
<div class="stat-label">record types</div>
108
134
</div>
109
-
</div>
110
-
<div class="tree-item">
111
-
<div class="tree-item-header">
112
-
<span style="color: var(--text-light);">handle</span>
113
-
<span style="font-size: 0.6rem; color: var(--text);">@${handle}</span>
135
+
<div class="stat">
136
+
<div class="stat-value">${appCount}</div>
137
+
<div class="stat-label">apps</div>
114
138
</div>
115
139
</div>
116
-
<div class="tree-item">
117
-
<div class="tree-item-header">
118
-
<span style="color: var(--text-light);">personal data server</span>
119
-
<span style="font-size: 0.6rem; color: var(--text);">${pds}</span>
120
-
</div>
140
+
141
+
<div class="ownership-box">
142
+
<div class="ownership-header">on traditional platforms</div>
143
+
<div class="ownership-text">your content is locked in. switching platforms means starting over. you build their network, they own the distribution.</div>
121
144
</div>
122
-
<div style="margin-top: 1rem; padding: 0.6rem; background: var(--bg); border-radius: 4px; font-size: 0.65rem; line-height: 1.5; color: var(--text-lighter);">
123
-
your data lives at <strong style="color: var(--text);">${pdsHost}</strong>. apps like bluesky write to and read from this server. you control @<strong style="color: var(--text);">${handle}</strong> and can move it to a different server anytime.
145
+
146
+
<div class="ownership-box yours">
147
+
<div class="ownership-header">on atproto</div>
148
+
<div class="ownership-text">your content, your server. apps just read and write to <strong>${pdsHost}</strong>. switch apps anytime, take your data anywhere.</div>
124
149
</div>
150
+
151
+
<div style="margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--border);">
152
+
<div style="font-size: 0.65rem; color: var(--text-light); margin-bottom: 0.5rem;">technical details</div>
153
+
<div class="tree-item">
154
+
<div class="tree-item-header">
155
+
<span style="color: var(--text-light);">did</span>
156
+
<span style="font-size: 0.55rem; color: var(--text);">${did}</span>
157
+
</div>
158
+
</div>
159
+
<div class="tree-item">
160
+
<div class="tree-item-header">
161
+
<span style="color: var(--text-light);">handle</span>
162
+
<span style="font-size: 0.6rem; color: var(--text);">@${globalHandle}</span>
163
+
</div>
164
+
</div>
165
+
</div>
125
166
`;
126
167
detail.classList.add('visible');
127
168
···
129
170
130
171
131
172
173
+
});
174
+
});
132
175
133
-
134
-
135
-
136
-
137
-
138
-
.then(r => r.json())
139
-
.then(repo => {
140
-
const collections = repo.collections || [];
141
-
142
-
// Group by app namespace (first two parts of lexicon)
143
-
const apps = {};
176
+
const field = document.getElementById('field');
177
+
field.innerHTML = '';
178
+
field.classList.remove('loading');
+3
-3
static/onboarding.js
+3
-3
static/onboarding.js
···
5
5
{
6
6
target: '.identity',
7
7
title: 'this is you',
8
-
description: 'your global identity and handle. your data is hosted at your personal data server (pds).',
8
+
description: 'your global identity and handle. your data is hosted at your <a href="https://atproto.com/guides/overview" target="_blank" rel="noopener noreferrer" style="color: inherit; text-decoration: underline;">Personal Data Server (PDS)</a>.',
9
9
position: 'bottom'
10
10
},
11
11
{
12
12
target: '.canvas',
13
13
title: 'third-party applications',
14
-
description: 'these apps use your global identity to write public records to your pds. they can also read records you\'ve created.',
14
+
description: 'these apps use your global identity to write public records to your PDS. they can also read records you\'ve created.',
15
15
position: 'center'
16
16
},
17
17
{
18
18
target: '.app-view',
19
19
title: 'explore your records',
20
-
description: 'click any app to see what records it has written to your pds.',
20
+
description: 'click any app to see what records it has written to your PDS.',
21
21
position: 'bottom'
22
22
}
23
23
];
History
1 round
0 comments
zzstoatzz.io
submitted
#0
4 commits
expand
collapse
feat: add ownership visualization and silo comparison
- show stats (record types, apps) when clicking identity
- contrast walled gardens vs atproto ownership
- update info modal to emphasize ownership
- add visual styling for ownership boxes
fix: scope issue with apps variable and soften messaging
- move identity click handler after apps is populated
- change messaging from ban-focused to lock-in/distribution focused
- emphasize 'you build their network, they own distribution'
- softer language: locked in vs can't export, starting over vs gone
feat: capitalize PDS and add link to official docs
- capitalize Personal Data Server (PDS) throughout
- link first mention in info modal to atproto.com/guides/overview
- update meta descriptions and onboarding text
feat: link PDS in first onboarding step to official docs
expand 0 comments
pull request successfully merged