+3
Makefile
+3
Makefile
+18
README.md
+18
README.md
···
1
+
# ligo.at
2
+
3
+
A decentralized links page powered by the [AT Protocol][atproto].
4
+
5
+
## dependencies
6
+
7
+
Install [uv][uv] and run `uv sync`.
8
+
9
+
## generate secrets
10
+
11
+
Use the `generate_secrets.py` script or run `make .env`.
12
+
13
+
## run
14
+
15
+
Either start a debug server with `make debug` or a production one with `make run`. Production needs the `PORT` environment variable.
16
+
17
+
[atproto]: https://atproto.com
18
+
[uv]: https://docs.astral.sh/uv/
+16
generate_secrets.py
+16
generate_secrets.py
···
1
+
import secrets
2
+
import time
3
+
from authlib.jose import JsonWebKey
4
+
5
+
6
+
if __name__ == "__main__":
7
+
secret_key = secrets.token_hex()
8
+
9
+
now = int(time.time())
10
+
key = JsonWebKey.generate_key(
11
+
"EC", "P-256", options={"kid": f"demo-{now}"}, is_private=True
12
+
)
13
+
client_secret_jwk = key.as_json(is_private=True)
14
+
15
+
print(f'FLASK_SECRET_KEY="{secret_key}"')
16
+
print(f"FLASK_CLIENT_SECRET_JWK={client_secret_jwk}")
-29
requirements.txt
-29
requirements.txt
···
1
-
annotated-types==0.7.0
2
-
anyio==4.11.0
3
-
atproto==0.0.62
4
-
blinker==1.9.0
5
-
certifi==2025.10.5
6
-
cffi==2.0.0
7
-
click==8.3.0
8
-
cryptography==45.0.7
9
-
dnspython==2.8.0
10
-
Flask==3.1.2
11
-
gunicorn==23.0.0
12
-
h11==0.16.0
13
-
httpcore==1.0.9
14
-
httpx==0.28.1
15
-
idna==3.10
16
-
itsdangerous==2.2.0
17
-
Jinja2==3.1.6
18
-
libipld==3.1.1
19
-
MarkupSafe==3.0.3
20
-
packaging==25.0
21
-
pycparser==2.23
22
-
pydantic==2.11.10
23
-
pydantic_core==2.33.2
24
-
python-dotenv==1.1.1
25
-
sniffio==1.3.1
26
-
typing-inspection==0.4.2
27
-
typing_extensions==4.15.0
28
-
websockets==13.1
29
-
Werkzeug==3.1.3