tangled
alpha
login
or
join now
minito.dev
/
SkeetLonger.app
1
fork
atom
A web app for writing and sharing 301+ character Bluesky posts.
1
fork
atom
overview
issues
pulls
pipelines
Successful push to PDS
Minito
4 months ago
ed1f33e4
9830f505
+746
-28
8 changed files
expand all
collapse all
unified
split
package-lock.json
package.json
src
App.tsx
main.tsx
routeTree.gen.ts
routes
__root.tsx
about.tsx
index.tsx
+454
-1
package-lock.json
···
9
"version": "0.0.0",
10
"dependencies": {
11
"@atproto/api": "^0.16.11",
0
12
"@atproto/oauth-client-browser": "^0.3.33",
13
"@tailwindcss/vite": "^4.1.14",
14
"react": "^19.1.1",
15
"react-dom": "^19.1.1",
16
-
"tailwindcss": "^4.1.14"
17
},
18
"devDependencies": {
19
"@eslint/js": "^9.36.0",
···
146
"multiformats": "^9.9.0",
147
"tlds": "^1.234.0",
148
"zod": "^3.23.8"
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
149
}
150
},
151
"node_modules/@atproto/common-web": {
···
743
"node": ">=6.9.0"
744
}
745
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
746
"node_modules/@esbuild/aix-ppc64": {
747
"version": "0.25.11",
748
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz",
···
1403
},
1404
"funding": {
1405
"url": "https://github.com/sponsors/sindresorhus"
0
0
0
0
0
0
0
0
0
0
1406
}
1407
},
1408
"node_modules/@isaacs/fs-minipass": {
···
2644
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
2645
}
2646
},
0
0
0
0
0
0
0
0
0
0
0
0
2647
"node_modules/acorn": {
2648
"version": "8.15.0",
2649
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
···
2744
"node": ">=4"
2745
}
2746
},
0
0
0
0
0
0
0
0
0
2747
"node_modules/await-lock": {
2748
"version": "2.2.2",
2749
"resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz",
···
2780
"dev": true,
2781
"license": "MIT"
2782
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
2783
"node_modules/baseline-browser-mapping": {
2784
"version": "2.8.18",
2785
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.18.tgz",
···
2861
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
2862
}
2863
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
2864
"node_modules/callsites": {
2865
"version": "3.1.0",
2866
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
···
2891
}
2892
],
2893
"license": "CC-BY-4.0"
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
2894
},
2895
"node_modules/chalk": {
2896
"version": "4.1.2",
···
3366
"node": ">=0.10.0"
3367
}
3368
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
3369
"node_modules/exsolve": {
3370
"version": "1.0.7",
3371
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
···
3423
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
3424
"dev": true,
3425
"license": "MIT"
0
0
0
0
0
0
0
0
0
3426
},
3427
"node_modules/fastq": {
3428
"version": "1.19.1",
···
3582
"engines": {
3583
"node": ">=8"
3584
}
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
3585
},
3586
"node_modules/ignore": {
3587
"version": "5.3.2",
···
4221
"dev": true,
4222
"license": "MIT"
4223
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4224
"node_modules/node-releases": {
4225
"version": "2.0.25",
4226
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.25.tgz",
···
4236
"license": "MIT",
4237
"engines": {
4238
"node": ">=0.10.0"
0
0
0
0
0
0
0
0
0
4239
}
4240
},
4241
"node_modules/optionator": {
···
4354
"url": "https://github.com/sponsors/jonschlinkert"
4355
}
4356
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4357
"node_modules/pkg-types": {
4358
"version": "2.3.0",
4359
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz",
···
4420
"url": "https://github.com/prettier/prettier?sponsor=1"
4421
}
4422
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4423
"node_modules/punycode": {
4424
"version": "2.3.1",
4425
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
···
4468
],
4469
"license": "MIT"
4470
},
0
0
0
0
0
0
4471
"node_modules/react": {
4472
"version": "19.2.0",
4473
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
···
4499
"node": ">=0.10.0"
4500
}
4501
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4502
"node_modules/readdirp": {
4503
"version": "3.6.0",
4504
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
···
4510
},
4511
"engines": {
4512
"node": ">=8.10.0"
0
0
0
0
0
0
0
0
0
4513
}
4514
},
4515
"node_modules/recast": {
···
4635
"queue-microtask": "^1.2.2"
4636
}
4637
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4638
"node_modules/scheduler": {
4639
"version": "0.27.0",
4640
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
···
4704
"node": ">=8"
4705
}
4706
},
0
0
0
0
0
0
0
0
0
4707
"node_modules/source-map": {
4708
"version": "0.7.6",
4709
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
···
4723
"node": ">=0.10.0"
4724
}
4725
},
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4726
"node_modules/strip-json-comments": {
4727
"version": "3.1.1",
4728
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
···
4811
"license": "BlueOak-1.0.0",
4812
"engines": {
4813
"node": ">=18"
0
0
0
0
0
0
0
0
0
4814
}
4815
},
4816
"node_modules/tiny-invariant": {
···
4952
},
4953
"engines": {
4954
"node": ">= 0.8.0"
0
0
0
0
0
0
0
0
0
4955
}
4956
},
4957
"node_modules/typescript": {
···
5266
"license": "MIT",
5267
"peerDependencies": {
5268
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
0
0
0
0
0
0
0
0
0
0
0
0
0
5269
}
5270
},
5271
"node_modules/vite": {
···
9
"version": "0.0.0",
10
"dependencies": {
11
"@atproto/api": "^0.16.11",
12
+
"@atproto/common": "^0.4.12",
13
"@atproto/oauth-client-browser": "^0.3.33",
14
"@tailwindcss/vite": "^4.1.14",
15
"react": "^19.1.1",
16
"react-dom": "^19.1.1",
17
+
"tailwindcss": "^4.1.14",
18
},
19
"devDependencies": {
20
"@eslint/js": "^9.36.0",
···
147
"multiformats": "^9.9.0",
148
"tlds": "^1.234.0",
149
"zod": "^3.23.8"
150
+
}
151
+
},
152
+
"node_modules/@atproto/common": {
153
+
"version": "0.4.12",
154
+
"resolved": "https://registry.npmjs.org/@atproto/common/-/common-0.4.12.tgz",
155
+
"integrity": "sha512-NC+TULLQiqs6MvNymhQS5WDms3SlbIKGLf4n33tpftRJcalh507rI+snbcUb7TLIkKw7VO17qMqxEXtIdd5auQ==",
156
+
"license": "MIT",
157
+
"dependencies": {
158
+
"@atproto/common-web": "^0.4.3",
159
+
"@ipld/dag-cbor": "^7.0.3",
160
+
"cbor-x": "^1.5.1",
161
+
"iso-datestring-validator": "^2.2.2",
162
+
"multiformats": "^9.9.0",
163
+
"pino": "^8.21.0"
164
+
},
165
+
"engines": {
166
+
"node": ">=18.7.0"
167
}
168
},
169
"node_modules/@atproto/common-web": {
···
761
"node": ">=6.9.0"
762
}
763
},
764
+
"node_modules/@cbor-extract/cbor-extract-darwin-arm64": {
765
+
"version": "2.2.0",
766
+
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz",
767
+
"integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==",
768
+
"cpu": [
769
+
"arm64"
770
+
],
771
+
"license": "MIT",
772
+
"optional": true,
773
+
"os": [
774
+
"darwin"
775
+
]
776
+
},
777
+
"node_modules/@cbor-extract/cbor-extract-darwin-x64": {
778
+
"version": "2.2.0",
779
+
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz",
780
+
"integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==",
781
+
"cpu": [
782
+
"x64"
783
+
],
784
+
"license": "MIT",
785
+
"optional": true,
786
+
"os": [
787
+
"darwin"
788
+
]
789
+
},
790
+
"node_modules/@cbor-extract/cbor-extract-linux-arm": {
791
+
"version": "2.2.0",
792
+
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz",
793
+
"integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==",
794
+
"cpu": [
795
+
"arm"
796
+
],
797
+
"license": "MIT",
798
+
"optional": true,
799
+
"os": [
800
+
"linux"
801
+
]
802
+
},
803
+
"node_modules/@cbor-extract/cbor-extract-linux-arm64": {
804
+
"version": "2.2.0",
805
+
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz",
806
+
"integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==",
807
+
"cpu": [
808
+
"arm64"
809
+
],
810
+
"license": "MIT",
811
+
"optional": true,
812
+
"os": [
813
+
"linux"
814
+
]
815
+
},
816
+
"node_modules/@cbor-extract/cbor-extract-linux-x64": {
817
+
"version": "2.2.0",
818
+
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz",
819
+
"integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==",
820
+
"cpu": [
821
+
"x64"
822
+
],
823
+
"license": "MIT",
824
+
"optional": true,
825
+
"os": [
826
+
"linux"
827
+
]
828
+
},
829
+
"node_modules/@cbor-extract/cbor-extract-win32-x64": {
830
+
"version": "2.2.0",
831
+
"resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz",
832
+
"integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==",
833
+
"cpu": [
834
+
"x64"
835
+
],
836
+
"license": "MIT",
837
+
"optional": true,
838
+
"os": [
839
+
"win32"
840
+
]
841
+
},
842
"node_modules/@esbuild/aix-ppc64": {
843
"version": "0.25.11",
844
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz",
···
1499
},
1500
"funding": {
1501
"url": "https://github.com/sponsors/sindresorhus"
1502
+
}
1503
+
},
1504
+
"node_modules/@ipld/dag-cbor": {
1505
+
"version": "7.0.3",
1506
+
"resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-7.0.3.tgz",
1507
+
"integrity": "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==",
1508
+
"license": "(Apache-2.0 AND MIT)",
1509
+
"dependencies": {
1510
+
"cborg": "^1.6.0",
1511
+
"multiformats": "^9.5.4"
1512
}
1513
},
1514
"node_modules/@isaacs/fs-minipass": {
···
2750
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
2751
}
2752
},
2753
+
"node_modules/abort-controller": {
2754
+
"version": "3.0.0",
2755
+
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
2756
+
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
2757
+
"license": "MIT",
2758
+
"dependencies": {
2759
+
"event-target-shim": "^5.0.0"
2760
+
},
2761
+
"engines": {
2762
+
"node": ">=6.5"
2763
+
}
2764
+
},
2765
"node_modules/acorn": {
2766
"version": "8.15.0",
2767
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
···
2862
"node": ">=4"
2863
}
2864
},
2865
+
"node_modules/atomic-sleep": {
2866
+
"version": "1.0.0",
2867
+
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
2868
+
"integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
2869
+
"license": "MIT",
2870
+
"engines": {
2871
+
"node": ">=8.0.0"
2872
+
}
2873
+
},
2874
"node_modules/await-lock": {
2875
"version": "2.2.2",
2876
"resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz",
···
2907
"dev": true,
2908
"license": "MIT"
2909
},
2910
+
"node_modules/base64-js": {
2911
+
"version": "1.5.1",
2912
+
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
2913
+
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
2914
+
"funding": [
2915
+
{
2916
+
"type": "github",
2917
+
"url": "https://github.com/sponsors/feross"
2918
+
},
2919
+
{
2920
+
"type": "patreon",
2921
+
"url": "https://www.patreon.com/feross"
2922
+
},
2923
+
{
2924
+
"type": "consulting",
2925
+
"url": "https://feross.org/support"
2926
+
}
2927
+
],
2928
+
"license": "MIT"
2929
+
},
2930
"node_modules/baseline-browser-mapping": {
2931
"version": "2.8.18",
2932
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.18.tgz",
···
3008
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
3009
}
3010
},
3011
+
"node_modules/buffer": {
3012
+
"version": "6.0.3",
3013
+
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
3014
+
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
3015
+
"funding": [
3016
+
{
3017
+
"type": "github",
3018
+
"url": "https://github.com/sponsors/feross"
3019
+
},
3020
+
{
3021
+
"type": "patreon",
3022
+
"url": "https://www.patreon.com/feross"
3023
+
},
3024
+
{
3025
+
"type": "consulting",
3026
+
"url": "https://feross.org/support"
3027
+
}
3028
+
],
3029
+
"license": "MIT",
3030
+
"dependencies": {
3031
+
"base64-js": "^1.3.1",
3032
+
"ieee754": "^1.2.1"
3033
+
}
3034
+
},
3035
"node_modules/callsites": {
3036
"version": "3.1.0",
3037
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
···
3062
}
3063
],
3064
"license": "CC-BY-4.0"
3065
+
},
3066
+
"node_modules/cbor-extract": {
3067
+
"version": "2.2.0",
3068
+
"resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz",
3069
+
"integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==",
3070
+
"hasInstallScript": true,
3071
+
"license": "MIT",
3072
+
"optional": true,
3073
+
"dependencies": {
3074
+
"node-gyp-build-optional-packages": "5.1.1"
3075
+
},
3076
+
"bin": {
3077
+
"download-cbor-prebuilds": "bin/download-prebuilds.js"
3078
+
},
3079
+
"optionalDependencies": {
3080
+
"@cbor-extract/cbor-extract-darwin-arm64": "2.2.0",
3081
+
"@cbor-extract/cbor-extract-darwin-x64": "2.2.0",
3082
+
"@cbor-extract/cbor-extract-linux-arm": "2.2.0",
3083
+
"@cbor-extract/cbor-extract-linux-arm64": "2.2.0",
3084
+
"@cbor-extract/cbor-extract-linux-x64": "2.2.0",
3085
+
"@cbor-extract/cbor-extract-win32-x64": "2.2.0"
3086
+
}
3087
+
},
3088
+
"node_modules/cbor-x": {
3089
+
"version": "1.6.0",
3090
+
"resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.6.0.tgz",
3091
+
"integrity": "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==",
3092
+
"license": "MIT",
3093
+
"optionalDependencies": {
3094
+
"cbor-extract": "^2.2.0"
3095
+
}
3096
+
},
3097
+
"node_modules/cborg": {
3098
+
"version": "1.10.2",
3099
+
"resolved": "https://registry.npmjs.org/cborg/-/cborg-1.10.2.tgz",
3100
+
"integrity": "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==",
3101
+
"license": "Apache-2.0",
3102
+
"bin": {
3103
+
"cborg": "cli.js"
3104
+
}
3105
},
3106
"node_modules/chalk": {
3107
"version": "4.1.2",
···
3577
"node": ">=0.10.0"
3578
}
3579
},
3580
+
"node_modules/event-target-shim": {
3581
+
"version": "5.0.1",
3582
+
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
3583
+
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
3584
+
"license": "MIT",
3585
+
"engines": {
3586
+
"node": ">=6"
3587
+
}
3588
+
},
3589
+
"node_modules/events": {
3590
+
"version": "3.3.0",
3591
+
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
3592
+
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
3593
+
"license": "MIT",
3594
+
"engines": {
3595
+
"node": ">=0.8.x"
3596
+
}
3597
+
},
3598
"node_modules/exsolve": {
3599
"version": "1.0.7",
3600
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
···
3652
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
3653
"dev": true,
3654
"license": "MIT"
3655
+
},
3656
+
"node_modules/fast-redact": {
3657
+
"version": "3.5.0",
3658
+
"resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz",
3659
+
"integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==",
3660
+
"license": "MIT",
3661
+
"engines": {
3662
+
"node": ">=6"
3663
+
}
3664
},
3665
"node_modules/fastq": {
3666
"version": "1.19.1",
···
3820
"engines": {
3821
"node": ">=8"
3822
}
3823
+
},
3824
+
"node_modules/ieee754": {
3825
+
"version": "1.2.1",
3826
+
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
3827
+
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
3828
+
"funding": [
3829
+
{
3830
+
"type": "github",
3831
+
"url": "https://github.com/sponsors/feross"
3832
+
},
3833
+
{
3834
+
"type": "patreon",
3835
+
"url": "https://www.patreon.com/feross"
3836
+
},
3837
+
{
3838
+
"type": "consulting",
3839
+
"url": "https://feross.org/support"
3840
+
}
3841
+
],
3842
+
"license": "BSD-3-Clause"
3843
},
3844
"node_modules/ignore": {
3845
"version": "5.3.2",
···
4479
"dev": true,
4480
"license": "MIT"
4481
},
4482
+
"node_modules/node-gyp-build-optional-packages": {
4483
+
"version": "5.1.1",
4484
+
"resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz",
4485
+
"integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==",
4486
+
"license": "MIT",
4487
+
"optional": true,
4488
+
"dependencies": {
4489
+
"detect-libc": "^2.0.1"
4490
+
},
4491
+
"bin": {
4492
+
"node-gyp-build-optional-packages": "bin.js",
4493
+
"node-gyp-build-optional-packages-optional": "optional.js",
4494
+
"node-gyp-build-optional-packages-test": "build-test.js"
4495
+
}
4496
+
},
4497
"node_modules/node-releases": {
4498
"version": "2.0.25",
4499
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.25.tgz",
···
4509
"license": "MIT",
4510
"engines": {
4511
"node": ">=0.10.0"
4512
+
}
4513
+
},
4514
+
"node_modules/on-exit-leak-free": {
4515
+
"version": "2.1.2",
4516
+
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
4517
+
"integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
4518
+
"license": "MIT",
4519
+
"engines": {
4520
+
"node": ">=14.0.0"
4521
}
4522
},
4523
"node_modules/optionator": {
···
4636
"url": "https://github.com/sponsors/jonschlinkert"
4637
}
4638
},
4639
+
"node_modules/pino": {
4640
+
"version": "8.21.0",
4641
+
"resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz",
4642
+
"integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==",
4643
+
"license": "MIT",
4644
+
"dependencies": {
4645
+
"atomic-sleep": "^1.0.0",
4646
+
"fast-redact": "^3.1.1",
4647
+
"on-exit-leak-free": "^2.1.0",
4648
+
"pino-abstract-transport": "^1.2.0",
4649
+
"pino-std-serializers": "^6.0.0",
4650
+
"process-warning": "^3.0.0",
4651
+
"quick-format-unescaped": "^4.0.3",
4652
+
"real-require": "^0.2.0",
4653
+
"safe-stable-stringify": "^2.3.1",
4654
+
"sonic-boom": "^3.7.0",
4655
+
"thread-stream": "^2.6.0"
4656
+
},
4657
+
"bin": {
4658
+
"pino": "bin.js"
4659
+
}
4660
+
},
4661
+
"node_modules/pino-abstract-transport": {
4662
+
"version": "1.2.0",
4663
+
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz",
4664
+
"integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==",
4665
+
"license": "MIT",
4666
+
"dependencies": {
4667
+
"readable-stream": "^4.0.0",
4668
+
"split2": "^4.0.0"
4669
+
}
4670
+
},
4671
+
"node_modules/pino-std-serializers": {
4672
+
"version": "6.2.2",
4673
+
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz",
4674
+
"integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==",
4675
+
"license": "MIT"
4676
+
},
4677
"node_modules/pkg-types": {
4678
"version": "2.3.0",
4679
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz",
···
4740
"url": "https://github.com/prettier/prettier?sponsor=1"
4741
}
4742
},
4743
+
"node_modules/process": {
4744
+
"version": "0.11.10",
4745
+
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
4746
+
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
4747
+
"license": "MIT",
4748
+
"engines": {
4749
+
"node": ">= 0.6.0"
4750
+
}
4751
+
},
4752
+
"node_modules/process-warning": {
4753
+
"version": "3.0.0",
4754
+
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz",
4755
+
"integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==",
4756
+
"license": "MIT"
4757
+
},
4758
"node_modules/punycode": {
4759
"version": "2.3.1",
4760
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
···
4803
],
4804
"license": "MIT"
4805
},
4806
+
"node_modules/quick-format-unescaped": {
4807
+
"version": "4.0.4",
4808
+
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
4809
+
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
4810
+
"license": "MIT"
4811
+
},
4812
"node_modules/react": {
4813
"version": "19.2.0",
4814
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
···
4840
"node": ">=0.10.0"
4841
}
4842
},
4843
+
"node_modules/readable-stream": {
4844
+
"version": "4.7.0",
4845
+
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
4846
+
"integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
4847
+
"license": "MIT",
4848
+
"dependencies": {
4849
+
"abort-controller": "^3.0.0",
4850
+
"buffer": "^6.0.3",
4851
+
"events": "^3.3.0",
4852
+
"process": "^0.11.10",
4853
+
"string_decoder": "^1.3.0"
4854
+
},
4855
+
"engines": {
4856
+
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
4857
+
}
4858
+
},
4859
"node_modules/readdirp": {
4860
"version": "3.6.0",
4861
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
···
4867
},
4868
"engines": {
4869
"node": ">=8.10.0"
4870
+
}
4871
+
},
4872
+
"node_modules/real-require": {
4873
+
"version": "0.2.0",
4874
+
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
4875
+
"integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
4876
+
"license": "MIT",
4877
+
"engines": {
4878
+
"node": ">= 12.13.0"
4879
}
4880
},
4881
"node_modules/recast": {
···
5001
"queue-microtask": "^1.2.2"
5002
}
5003
},
5004
+
"node_modules/safe-buffer": {
5005
+
"version": "5.2.1",
5006
+
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
5007
+
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
5008
+
"funding": [
5009
+
{
5010
+
"type": "github",
5011
+
"url": "https://github.com/sponsors/feross"
5012
+
},
5013
+
{
5014
+
"type": "patreon",
5015
+
"url": "https://www.patreon.com/feross"
5016
+
},
5017
+
{
5018
+
"type": "consulting",
5019
+
"url": "https://feross.org/support"
5020
+
}
5021
+
],
5022
+
"license": "MIT"
5023
+
},
5024
+
"node_modules/safe-stable-stringify": {
5025
+
"version": "2.5.0",
5026
+
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
5027
+
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
5028
+
"license": "MIT",
5029
+
"engines": {
5030
+
"node": ">=10"
5031
+
}
5032
+
},
5033
"node_modules/scheduler": {
5034
"version": "0.27.0",
5035
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
···
5099
"node": ">=8"
5100
}
5101
},
5102
+
"node_modules/sonic-boom": {
5103
+
"version": "3.8.1",
5104
+
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz",
5105
+
"integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==",
5106
+
"license": "MIT",
5107
+
"dependencies": {
5108
+
"atomic-sleep": "^1.0.0"
5109
+
}
5110
+
},
5111
"node_modules/source-map": {
5112
"version": "0.7.6",
5113
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
···
5127
"node": ">=0.10.0"
5128
}
5129
},
5130
+
"node_modules/split2": {
5131
+
"version": "4.2.0",
5132
+
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
5133
+
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
5134
+
"license": "ISC",
5135
+
"engines": {
5136
+
"node": ">= 10.x"
5137
+
}
5138
+
},
5139
+
"node_modules/string_decoder": {
5140
+
"version": "1.3.0",
5141
+
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
5142
+
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
5143
+
"license": "MIT",
5144
+
"dependencies": {
5145
+
"safe-buffer": "~5.2.0"
5146
+
}
5147
+
},
5148
"node_modules/strip-json-comments": {
5149
"version": "3.1.1",
5150
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
···
5233
"license": "BlueOak-1.0.0",
5234
"engines": {
5235
"node": ">=18"
5236
+
}
5237
+
},
5238
+
"node_modules/thread-stream": {
5239
+
"version": "2.7.0",
5240
+
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz",
5241
+
"integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==",
5242
+
"license": "MIT",
5243
+
"dependencies": {
5244
+
"real-require": "^0.2.0"
5245
}
5246
},
5247
"node_modules/tiny-invariant": {
···
5383
},
5384
"engines": {
5385
"node": ">= 0.8.0"
5386
+
}
5387
+
},
5388
+
"node_modules/typeid-js": {
5389
+
"version": "1.2.0",
5390
+
"resolved": "https://registry.npmjs.org/typeid-js/-/typeid-js-1.2.0.tgz",
5391
+
"integrity": "sha512-t76ZucAnvGC60ea/HjVsB0TSoB0cw9yjnfurUgtInXQWUI/VcrlZGpO23KN3iSe8yOGUgb1zr7W7uEzJ3hSljA==",
5392
+
"license": "Apache-2.0",
5393
+
"dependencies": {
5394
+
"uuid": "^10.0.0"
5395
}
5396
},
5397
"node_modules/typescript": {
···
5706
"license": "MIT",
5707
"peerDependencies": {
5708
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
5709
+
}
5710
+
},
5711
+
"node_modules/uuid": {
5712
+
"version": "10.0.0",
5713
+
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
5714
+
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
5715
+
"funding": [
5716
+
"https://github.com/sponsors/broofa",
5717
+
"https://github.com/sponsors/ctavan"
5718
+
],
5719
+
"license": "MIT",
5720
+
"bin": {
5721
+
"uuid": "dist/bin/uuid"
5722
}
5723
},
5724
"node_modules/vite": {
+3
-1
package.json
···
11
},
12
"dependencies": {
13
"@atproto/api": "^0.16.11",
0
14
"@atproto/oauth-client-browser": "^0.3.33",
15
"@tailwindcss/vite": "^4.1.14",
16
"react": "^19.1.1",
17
"react-dom": "^19.1.1",
18
-
"tailwindcss": "^4.1.14"
0
19
},
20
"devDependencies": {
21
"@eslint/js": "^9.36.0",
···
11
},
12
"dependencies": {
13
"@atproto/api": "^0.16.11",
14
+
"@atproto/common": "^0.4.12",
15
"@atproto/oauth-client-browser": "^0.3.33",
16
"@tailwindcss/vite": "^4.1.14",
17
"react": "^19.1.1",
18
"react-dom": "^19.1.1",
19
+
"tailwindcss": "^4.1.14",
20
+
"typeid-js": "^1.2.0"
21
},
22
"devDependencies": {
23
"@eslint/js": "^9.36.0",
+19
-2
src/App.tsx
···
2
import './App.css'
3
import Login from './components/Login'
4
import { UnifiedAuthProvider } from './providers/UnifiedAuthProvider'
0
0
5
6
function App() {
0
0
7
const [postText, setPostText] = useState('')
8
const charCount = postText.length
9
10
-
const handleSubmit = async (e: React.FormEvent) => {
11
-
e.preventDefault();
0
0
0
0
0
0
0
0
0
0
0
0
12
// setError(null);
13
// try {
14
// localStorage.setItem("lastHandle", user);
···
53
</div>
54
55
<button
0
56
type='submit'
57
disabled={charCount < 300}
58
style={{ padding: '0.625rem 1.5rem', borderRadius: '0.5rem', fontSize: '0.875rem', fontWeight: '600', border: 'none', cursor: charCount === 0 ? 'not-allowed' : 'pointer', transition: 'background-color 0.2s', backgroundColor: charCount === 0 ? '#6b7280' : '#2563eb', color: 'white' }}
···
2
import './App.css'
3
import Login from './components/Login'
4
import { UnifiedAuthProvider } from './providers/UnifiedAuthProvider'
5
+
import { AtpAgent } from '@atproto/api'
6
+
// import { TID } from '@atproto/common'
7
8
function App() {
9
+
const agent = new AtpAgent({ service: 'https://skeetlonger.app' })
10
+
11
const [postText, setPostText] = useState('')
12
const charCount = postText.length
13
14
+
const handleSubmit = async () => {
15
+
// Generate a time-based key for our record
16
+
const rkey = "self"
17
+
18
+
await agent.com.atproto.repo.putRecord({
19
+
repo: agent.assertDid, // The user
20
+
collection: 'app.skeetlonger.post', // The collection
21
+
rkey, // The record key
22
+
record: { // The record value
23
+
post: postText,
24
+
createdAt: new Date().toISOString()
25
+
}
26
+
})
27
+
28
// setError(null);
29
// try {
30
// localStorage.setItem("lastHandle", user);
···
69
</div>
70
71
<button
72
+
onClick={() => handleSubmit()}
73
type='submit'
74
disabled={charCount < 300}
75
style={{ padding: '0.625rem 1.5rem', borderRadius: '0.5rem', fontSize: '0.875rem', fontWeight: '600', border: 'none', cursor: charCount === 0 ? 'not-allowed' : 'pointer', transition: 'background-color 0.2s', backgroundColor: charCount === 0 ? '#6b7280' : '#2563eb', color: 'white' }}
+14
-3
src/main.tsx
···
1
import { StrictMode } from 'react'
2
import { createRoot } from 'react-dom/client'
3
import './index.css'
4
-
import App from './App.tsx'
0
0
0
0
0
0
0
0
0
0
0
5
6
createRoot(document.getElementById('root')!).render(
7
<StrictMode>
8
-
<App />
9
</StrictMode>,
10
-
)
···
1
import { StrictMode } from 'react'
2
import { createRoot } from 'react-dom/client'
3
import './index.css'
4
+
import { RouterProvider, createRouter } from '@tanstack/react-router'
5
+
import { routeTree } from './routeTree.gen'
6
+
7
+
// Create a new router instance
8
+
const router = createRouter({ routeTree })
9
+
10
+
// Register the router instance for type safety
11
+
declare module '@tanstack/react-router' {
12
+
interface Register {
13
+
router: typeof router
14
+
}
15
+
}
16
17
createRoot(document.getElementById('root')!).render(
18
<StrictMode>
19
+
<RouterProvider router={router} />
20
</StrictMode>,
21
+
)
+50
-8
src/routeTree.gen.ts
···
9
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
10
11
import { Route as rootRouteImport } from './routes/__root'
0
0
12
13
-
export interface FileRoutesByFullPath {}
14
-
export interface FileRoutesByTo {}
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
15
export interface FileRoutesById {
16
__root__: typeof rootRouteImport
0
0
17
}
18
export interface FileRouteTypes {
19
fileRoutesByFullPath: FileRoutesByFullPath
20
-
fullPaths: never
21
fileRoutesByTo: FileRoutesByTo
22
-
to: never
23
-
id: '__root__'
24
fileRoutesById: FileRoutesById
25
}
26
-
export interface RootRouteChildren {}
0
0
0
27
28
declare module '@tanstack/react-router' {
29
-
interface FileRoutesByPath {}
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
30
}
31
32
-
const rootRouteChildren: RootRouteChildren = {}
0
0
0
33
export const routeTree = rootRouteImport
34
._addFileChildren(rootRouteChildren)
35
._addFileTypes<FileRouteTypes>()
···
9
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
10
11
import { Route as rootRouteImport } from './routes/__root'
12
+
import { Route as AboutRouteImport } from './routes/about'
13
+
import { Route as IndexRouteImport } from './routes/index'
14
15
+
const AboutRoute = AboutRouteImport.update({
16
+
id: '/about',
17
+
path: '/about',
18
+
getParentRoute: () => rootRouteImport,
19
+
} as any)
20
+
const IndexRoute = IndexRouteImport.update({
21
+
id: '/',
22
+
path: '/',
23
+
getParentRoute: () => rootRouteImport,
24
+
} as any)
25
+
26
+
export interface FileRoutesByFullPath {
27
+
'/': typeof IndexRoute
28
+
'/about': typeof AboutRoute
29
+
}
30
+
export interface FileRoutesByTo {
31
+
'/': typeof IndexRoute
32
+
'/about': typeof AboutRoute
33
+
}
34
export interface FileRoutesById {
35
__root__: typeof rootRouteImport
36
+
'/': typeof IndexRoute
37
+
'/about': typeof AboutRoute
38
}
39
export interface FileRouteTypes {
40
fileRoutesByFullPath: FileRoutesByFullPath
41
+
fullPaths: '/' | '/about'
42
fileRoutesByTo: FileRoutesByTo
43
+
to: '/' | '/about'
44
+
id: '__root__' | '/' | '/about'
45
fileRoutesById: FileRoutesById
46
}
47
+
export interface RootRouteChildren {
48
+
IndexRoute: typeof IndexRoute
49
+
AboutRoute: typeof AboutRoute
50
+
}
51
52
declare module '@tanstack/react-router' {
53
+
interface FileRoutesByPath {
54
+
'/about': {
55
+
id: '/about'
56
+
path: '/about'
57
+
fullPath: '/about'
58
+
preLoaderRoute: typeof AboutRouteImport
59
+
parentRoute: typeof rootRouteImport
60
+
}
61
+
'/': {
62
+
id: '/'
63
+
path: '/'
64
+
fullPath: '/'
65
+
preLoaderRoute: typeof IndexRouteImport
66
+
parentRoute: typeof rootRouteImport
67
+
}
68
+
}
69
}
70
71
+
const rootRouteChildren: RootRouteChildren = {
72
+
IndexRoute: IndexRoute,
73
+
AboutRoute: AboutRoute,
74
+
}
75
export const routeTree = rootRouteImport
76
._addFileChildren(rootRouteChildren)
77
._addFileTypes<FileRouteTypes>()
+4
-13
src/routes/__root.tsx
···
1
-
import * as React from 'react'
2
import { Outlet, createRootRoute } from '@tanstack/react-router'
3
import { UnifiedAuthProvider } from '../providers/UnifiedAuthProvider'
4
-
import Login from '../components/Login'
5
6
export const Route = createRootRoute({
7
component: RootComponent,
···
9
10
function RootComponent() {
11
return (
12
-
<React.Fragment>
13
-
<h1>SkeetLonger</h1>
14
-
15
-
<div className="flex items-center gap-2">
16
-
<UnifiedAuthProvider>
17
-
<Login compact={false}></Login>
18
-
</UnifiedAuthProvider>
19
-
</div>
20
-
<Outlet />
21
-
</React.Fragment>
22
)
23
-
}
···
0
1
import { Outlet, createRootRoute } from '@tanstack/react-router'
2
import { UnifiedAuthProvider } from '../providers/UnifiedAuthProvider'
0
3
4
export const Route = createRootRoute({
5
component: RootComponent,
···
7
8
function RootComponent() {
9
return (
10
+
<UnifiedAuthProvider>
11
+
<Outlet />
12
+
</UnifiedAuthProvider>
0
0
0
0
0
0
0
13
)
14
+
}
+102
src/routes/about.tsx
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
import { createFileRoute } from '@tanstack/react-router'
2
+
import Login from '../components/Login'
3
+
4
+
export const Route = createFileRoute('/about')({
5
+
component: AboutComponent,
6
+
})
7
+
8
+
function AboutComponent() {
9
+
return (
10
+
<>
11
+
<div style={{ position: 'fixed', top: '1rem', right: '1rem', zIndex: 9999 }}>
12
+
<Login compact={true} />
13
+
</div>
14
+
15
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', backgroundColor: '#242424' }}>
16
+
<div style={{ width: '100%', maxWidth: '72rem' }}>
17
+
{/* Title */}
18
+
<h1 style={{ fontSize: '2.25rem', fontWeight: 'bold', textAlign: 'center', marginBottom: '0.5rem', color: '#f3f4f6' }}>
19
+
About SkeetLonger
20
+
</h1>
21
+
<p style={{ textAlign: 'center', marginBottom: '2rem', color: '#9ca3af' }}>
22
+
Learn more about posting longer content to Bluesky
23
+
</p>
24
+
25
+
{/* Content Card */}
26
+
<div style={{ padding: '2rem', borderRadius: '0.75rem', boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1)', border: '1px solid #374151', backgroundColor: '#1a1a1a' }}>
27
+
28
+
{/* What is SkeetLonger */}
29
+
<section style={{ marginBottom: '2rem' }}>
30
+
<h2 style={{ fontSize: '1.5rem', fontWeight: '600', color: '#f3f4f6', marginBottom: '0.75rem' }}>
31
+
What is SkeetLonger?
32
+
</h2>
33
+
<p style={{ lineHeight: '1.75', color: '#d1d5db' }}>
34
+
SkeetLonger is a tool that allows you to post longer content to Bluesky,
35
+
bypassing the standard 300-character limit. Perfect for sharing detailed
36
+
thoughts, stories, or discussions without the constraints of short-form posts.
37
+
</p>
38
+
</section>
39
+
40
+
{/* How does it work */}
41
+
<section style={{ marginBottom: '2rem' }}>
42
+
<h2 style={{ fontSize: '1.5rem', fontWeight: '600', color: '#f3f4f6', marginBottom: '0.75rem' }}>
43
+
How does it work?
44
+
</h2>
45
+
<p style={{ lineHeight: '1.75', color: '#d1d5db' }}>
46
+
SkeetLonger stores your longer posts (300+ characters) as custom records in the AT Protocol.
47
+
These records are saved to your Personal Data Server (PDS) under the app.skeetlonger.post
48
+
collection, allowing you to write and preserve content beyond Bluesky's standard character
49
+
limits while maintaining full ownership of your data.
50
+
</p>
51
+
</section>
52
+
53
+
{/* Privacy & Security */}
54
+
<section style={{ marginBottom: '2rem' }}>
55
+
<h2 style={{ fontSize: '1.5rem', fontWeight: '600', color: '#f3f4f6', marginBottom: '0.75rem' }}>
56
+
Privacy & Security
57
+
</h2>
58
+
<p style={{ lineHeight: '1.75', color: '#d1d5db' }}>
59
+
SkeetLonger uses OAuth authentication, which means your password is never
60
+
shared with us. We only request the permissions necessary to post on your
61
+
behalf. You can revoke access at any time through your Bluesky settings.
62
+
</p>
63
+
</section>
64
+
65
+
{/* Open Source */}
66
+
<section style={{ marginBottom: '2rem' }}>
67
+
<h2 style={{ fontSize: '1.5rem', fontWeight: '600', color: '#f3f4f6', marginBottom: '0.75rem' }}>
68
+
Open Source
69
+
</h2>
70
+
<p style={{ lineHeight: '1.75', color: '#d1d5db' }}>
71
+
SkeetLonger is built with modern web technologies and is committed to
72
+
transparency. The AT Protocol (Authenticated Transfer Protocol) powers
73
+
Bluesky and enables tools like this to be built on top of the platform.
74
+
</p>
75
+
</section>
76
+
77
+
{/* Button */}
78
+
<div style={{ display: 'flex', justifyContent: 'center', paddingTop: '1rem', borderTop: '1px solid #374151' }}>
79
+
<a
80
+
href="/"
81
+
style={{
82
+
display: 'inline-block',
83
+
padding: '0.75rem 2rem',
84
+
borderRadius: '0.5rem',
85
+
backgroundColor: '#2563eb',
86
+
color: 'white',
87
+
fontWeight: '600',
88
+
textDecoration: 'none',
89
+
transition: 'background-color 0.2s'
90
+
}}
91
+
onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#1d4ed8'}
92
+
onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#2563eb'}
93
+
>
94
+
Start Writing
95
+
</a>
96
+
</div>
97
+
</div>
98
+
</div>
99
+
</div>
100
+
</>
101
+
)
102
+
}
+100
src/routes/index.tsx
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
import { createFileRoute } from '@tanstack/react-router'
2
+
import { useState } from 'react'
3
+
import '../App.css'
4
+
import Login from '../components/Login'
5
+
import { useAuth } from "../providers/UnifiedAuthProvider";
6
+
import { AtUri } from '@atproto/api';
7
+
8
+
export const Route = createFileRoute('/')({
9
+
component: RouteComponent,
10
+
})
11
+
12
+
function RouteComponent() {
13
+
const { agent } = useAuth();
14
+
15
+
const [postText, setPostText] = useState('')
16
+
const charCount = postText.length
17
+
18
+
const handleSubmit = async () => {
19
+
if (!agent) {
20
+
console.error("Agent not available");
21
+
return;
22
+
}
23
+
24
+
try {
25
+
// Create the record and let the server generate the rkey (TID)
26
+
const response = await agent.com.atproto.repo.createRecord({
27
+
repo: agent.assertDid,
28
+
collection: 'app.skeetlonger.post',
29
+
record: {
30
+
post: postText,
31
+
createdAt: new Date().toISOString()
32
+
}
33
+
});
34
+
35
+
// Parse the URI to extract the rkey
36
+
const uri = new AtUri(response.data.uri);
37
+
const rkey = uri.rkey;
38
+
39
+
console.log("Record created successfully!");
40
+
console.log("Full URI:", response.data.uri);
41
+
console.log("Extracted rkey:", rkey);
42
+
console.log("CID:", response.data.cid);
43
+
44
+
//setPostText(''); // Clear the textarea after posting
45
+
} catch (error) {
46
+
console.error("Failed to create record:", error);
47
+
}
48
+
};
49
+
50
+
return (
51
+
<>
52
+
<div style={{ position: 'fixed', top: '1rem', right: '1rem', zIndex: 9999 }}>
53
+
<Login compact={true} />
54
+
</div>
55
+
56
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: '5rem 1rem', backgroundColor: '#242424' }}>
57
+
<div style={{ width: '100%', maxWidth: '72rem' }}>
58
+
{/* Title */}
59
+
<h1 style={{ fontSize: '2.25rem', fontWeight: 'bold', textAlign: 'center', marginBottom: '0.5rem', color: '#f3f4f6' }}>
60
+
SkeetLonger
61
+
</h1>
62
+
<p style={{ textAlign: 'center', marginBottom: '2rem', color: '#9ca3af' }}>
63
+
Post longer content to Bluesky
64
+
</p>
65
+
66
+
{/* Text Editor Card */}
67
+
<div style={{ padding: '1.5rem', borderRadius: '0.75rem', boxShadow: '0 10px 15px -3px rgb(0 0 0 / 0.1)', border: '1px solid #e5e7eb', backgroundColor: '#1a1a1a', borderColor: '#374151' }}>
68
+
<textarea
69
+
value={postText}
70
+
onChange={(e) => setPostText(e.target.value)}
71
+
placeholder="What's on your mind? Write as much as you'd like..."
72
+
style={{ width: '32rem', height: '32rem', padding: '0.75rem 1rem', borderRadius: '0.5rem', border: '1px solid #4b5563', fontSize: '1rem', lineHeight: '1.75', resize: 'none', backgroundColor: '#111827', color: '#f3f4f6', boxSizing: 'border-box' }}
73
+
className="placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500"
74
+
/>
75
+
76
+
{/* Footer with character count and post button */}
77
+
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: '1rem' }}>
78
+
<div style={{ fontSize: '0.875rem' }}>
79
+
<span style={{ fontWeight: '500', color: charCount > 300 ? '#3b82f6' : '#9ca3af' }}>
80
+
{charCount} characters
81
+
</span>
82
+
</div>
83
+
84
+
<button
85
+
onClick={() => handleSubmit()}
86
+
type='submit'
87
+
disabled={charCount < 300}
88
+
style={{ padding: '0.625rem 1.5rem', borderRadius: '0.5rem', fontSize: '0.875rem', fontWeight: '600', border: 'none', cursor: charCount === 0 ? 'not-allowed' : 'pointer', transition: 'background-color 0.2s', backgroundColor: charCount === 0 ? '#6b7280' : '#2563eb', color: 'white' }}
89
+
onMouseEnter={(e) => { if (charCount !== 0) e.currentTarget.style.backgroundColor = '#1d4ed8'; }}
90
+
onMouseLeave={(e) => { if (charCount !== 0) e.currentTarget.style.backgroundColor = '#2563eb'; }}
91
+
>
92
+
Post
93
+
</button>
94
+
</div>
95
+
</div>
96
+
</div>
97
+
</div>
98
+
</>
99
+
)
100
+
}