decentralized and customizable links page on top of atproto

separate profile styles

-38
src/static/editor.css
··· 1 - link-editor-item { 2 - display: block; 3 - margin-top: 1em; 4 - margin-left: -0.25em; 5 - margin-right: -0.25em; 6 - padding: 0.25em; 7 - background: var(--color-background); 8 - border: 1px solid var(--color-border-secondary); 9 - border-radius: 2px; 10 - } 11 - 12 - link-editor-header { 13 - display: flex; 14 - flex-direction: row; 15 - gap: 0.25em; 16 - } 17 - 18 - link-editor-drag-handle { 19 - background: var(--color-background-secondary); 20 - display: flex; 21 - flex-grow: 0; 22 - padding: 2px; 23 - line-height: 100%; 24 - font-size: 1.5em; 25 - align-items: center; 26 - cursor: grab; 27 - } 28 - 29 - link-editor-drag-handle:active { 30 - cursor: grabbing; 31 - } 32 - 33 - link-editor-buttons { 34 - display: flex; 35 - flex-direction: row; 36 - gap: 0.25em; 37 - margin-top: 0.25em; 38 - }
+106
src/static/profile/default.css
··· 1 + :root { 2 + --color-background: #fff; 3 + --color-text: #333; 4 + --color-text-secondary: #696969; 5 + } 6 + 7 + @media (prefers-color-scheme: dark) { 8 + :root { 9 + --color-background: #111; 10 + --color-text: #fff; 11 + --color-text-secondary: #aaa; 12 + } 13 + } 14 + 15 + body { 16 + background: var(--color-background); 17 + color: var(--color-text); 18 + font-size: 18px; 19 + font-family: "Inter", system-ui, sans-serif, ui-sans-serif; 20 + font-feature-settings: 21 + "kern" 1, 22 + "liga" 1, 23 + "cv05" 1, 24 + "tnum" 1; 25 + font-optical-sizing: auto; 26 + font-variation-settings: normal; 27 + font-weight: 400; 28 + margin: 1rem; 29 + -moz-osx-font-smoothing: grayscale; 30 + -webkit-font-smoothing: antialiased; 31 + } 32 + 33 + a { 34 + color: inherit; 35 + } 36 + 37 + .wrapper { 38 + margin: auto; 39 + max-width: 25em; 40 + } 41 + 42 + .wrapper.profile { 43 + font-size: 20px; 44 + } 45 + 46 + header { 47 + margin: 2.5em 0; 48 + text-align: center; 49 + } 50 + 51 + header h1 { 52 + margin: 0; 53 + font-size: 1.5em; 54 + font-weight: inherit; 55 + } 56 + 57 + header .tagline { 58 + font-style: italic; 59 + display: block; 60 + margin-top: 0.5em; 61 + } 62 + 63 + .links-container ul { 64 + list-style: none; 65 + padding: 0; 66 + } 67 + 68 + .link-item { 69 + background: currentColor; 70 + display: block; 71 + padding: 0.5em; 72 + text-align: center; 73 + transition: transform 0.1s; 74 + box-shadow: -3px 3px 0 rgba(from currentColor r g b / 0.6); 75 + } 76 + 77 + .link-item .link-item-title { 78 + color: white; 79 + } 80 + 81 + .link-item .link-item-detail { 82 + color: white; 83 + display: block; 84 + font-size: 0.75em; 85 + opacity: 0.6; 86 + transition: opacity 0.3s; 87 + } 88 + 89 + .link-item:hover { 90 + transform: scale(1.05); 91 + } 92 + 93 + .link-item:hover .link-item-detail { 94 + opacity: 1; 95 + } 96 + 97 + .links-container li + li { 98 + margin-top: 0.75em; 99 + } 100 + 101 + footer { 102 + color: var(--color-text-secondary); 103 + font-size: 14px; 104 + margin: 5em 0; 105 + text-align: center; 106 + }
+45 -98
src/static/style.css
··· 1 + @import url(/static/profile/default.css); 2 + 1 3 :root { 2 4 --color-alert: #ee0000; 3 - --color-background: #fff; 4 5 --color-background-secondary: #eee; 5 6 --color-border: #bbb; 6 7 --color-border-secondary: #ddd; 7 - --color-text: #333; 8 - --color-text-secondary: #aaa; 9 8 } 10 9 11 10 @media (prefers-color-scheme: dark) { 12 11 :root { 13 - --color-background: #111; 14 12 --color-background-secondary: #333; 15 13 --color-border: #555; 16 14 --color-border-secondary: #333; 17 - --color-text: #fff; 18 15 } 19 16 } 20 17 21 - html { 22 - font-feature-settings: 23 - "kern" 1, 24 - "liga" 1, 25 - "cv05" 1, 26 - "tnum" 1; 27 - } 28 - 29 - body { 30 - background: var(--color-background); 31 - color: var(--color-text); 32 - font-size: 18px; 33 - font-family: "Inter", system-ui, sans-serif, ui-sans-serif; 34 - font-variation-settings: normal; 35 - font-weight: 400; 36 - font-optical-sizing: auto; 37 - margin: 1rem; 38 - -webkit-font-smoothing: antialiased; 39 - -moz-osx-font-smoothing: grayscale; 40 - } 41 - 42 - a { 43 - color: inherit; 44 - } 45 - 46 - .wrapper { 47 - margin: auto; 48 - max-width: 25rem; 18 + p { 19 + text-wrap: pretty; 49 20 } 50 21 51 22 .wrapper.error p { 52 23 text-align: center; 53 24 } 54 25 55 - header { 56 - margin: 2.5em 0; 57 - text-align: center; 58 - } 59 - 60 - header h1 { 61 - margin: 0; 62 - font-size: 1.5em; 63 - font-weight: inherit; 64 - } 65 - 66 26 h2 { 67 27 font-size: 1.3em; 68 28 font-weight: 500; 69 29 } 70 30 71 - header .tagline { 72 - font-style: italic; 73 - display: inline-block; 74 - margin-top: 0.5em; 75 - } 76 - 77 - ul { 78 - list-style: none; 79 - padding: 0; 80 - } 81 - 82 - .link-item { 83 - background: currentColor; 84 - display: block; 31 + .link-item.static { 85 32 flex-grow: 1; 86 - padding: 0.5em; 87 - text-align: center; 88 - transition: transform 0.1s; 33 + box-shadow: none; 89 34 } 90 35 91 - .link-item:not(.static) { 92 - box-shadow: -3px 3px 0 rgba(from currentColor r g b / 0.6); 93 - } 94 - 95 - .link-item-title { 96 - color: white; 97 - } 98 - 99 - .link-item .link-item-detail { 100 - color: white; 101 - display: block; 102 - font-size: 0.75em; 103 - opacity: 0.6; 104 - transition: opacity 0.3s; 105 - } 106 - 107 - .link-item:not(.static):hover { 108 - transform: scale(1.05); 109 - 110 - & .link-item-detail { 111 - opacity: 1; 112 - } 113 - } 114 - 115 - li:has(.link-item) + li:has(.link-item) { 116 - margin-top: 1rem; 117 - } 118 - 119 - li a { 120 - color: inherit; 121 - display: block; 122 - text-decoration: none; 36 + .link-item.static:hover { 37 + transform: none; 123 38 } 124 39 125 40 .alert { ··· 173 88 text-transform: uppercase; 174 89 } 175 90 176 - footer { 177 - color: var(--color-text-secondary); 178 - font-size: 14px; 179 - margin-top: 5em; 180 - text-align: center; 91 + link-editor-item { 92 + display: block; 93 + margin-top: 1em; 94 + margin-left: -0.25em; 95 + margin-right: -0.25em; 96 + padding: 0.25em; 97 + background: var(--color-background); 98 + border: 1px solid var(--color-border-secondary); 99 + border-radius: 2px; 100 + } 101 + 102 + link-editor-header { 103 + display: flex; 104 + flex-direction: row; 105 + gap: 0.25em; 106 + } 107 + 108 + link-editor-drag-handle { 109 + background: var(--color-background-secondary); 110 + display: flex; 111 + flex-grow: 0; 112 + padding: 2px; 113 + line-height: 100%; 114 + font-size: 1.5em; 115 + align-items: center; 116 + cursor: grab; 117 + } 118 + 119 + link-editor-drag-handle:active { 120 + cursor: grabbing; 121 + } 122 + 123 + link-editor-buttons { 124 + display: flex; 125 + flex-direction: row; 126 + gap: 0.25em; 127 + margin-top: 0.25em; 181 128 } 182 129 183 130 still-building {
+5
src/templates/_footerlinks.html
··· 1 + <p> 2 + <a href="{{ url_for('page_terms') }}">terms of service</a> 3 + <span>·</span> 4 + <a href="https://tangled.org/@ligo.at/core" target="_blank">source code</a> 5 + </p>
+5 -2
src/templates/editor.html
··· 5 5 <title>edit your profile &mdash; ligo.at</title> 6 6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /> 7 7 <link rel="stylesheet" href="{{ url_for('static', filename='inter.css') }}" /> 8 + <link rel="stylesheet" href="{{ url_for('static', filename='profile/default.css') }}" /> 8 9 <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" /> 9 - <link rel="stylesheet" href="{{ url_for('static', filename='editor.css') }}" /> 10 10 <link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16.png') }}" /> 11 11 <link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-32.png') }}" /> 12 12 <link rel="icon" type="image/png" sizes="48x48" href="{{ url_for('static', filename='favicon-48.png') }}" /> ··· 122 122 <!-- /editor/links --> 123 123 124 124 <footer> 125 - <a href="/">home</a> 125 + <p> 126 + <a href="/">home</a> 127 + </p> 128 + {% include "_footerlinks.html" %} 126 129 </footer> 127 130 </div> 128 131 <!-- .wrapper -->
+6 -4
src/templates/error.html
··· 2 2 <html> 3 3 <head> 4 4 <meta charset="utf-8" /> 5 - <title>not found &mdash; ligo.at</title> 5 + <title>oops! &mdash; ligo.at</title> 6 6 <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 7 <link rel="stylesheet" href="{{ url_for('static', filename='inter.css') }}" /> 8 + <link rel="stylesheet" href="{{ url_for('static', filename='profile/default.css') }}" /> 8 9 <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" /> 9 10 <link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16.png') }}" /> 10 11 <link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-32.png') }}" /> ··· 17 18 </header> 18 19 <p>{{ message }}</p> 19 20 <footer> 20 - <a href="/">home</a> 21 - <span>·</span> 22 - Made by <a href="/@nauta.one">@nauta.one</a> 21 + <p> 22 + <a href="/">home</a> 23 + </p> 24 + {% include "_footerlinks.html" %} 23 25 </footer> 24 26 </div> 25 27 </body>
+2 -5
src/templates/index.html
··· 5 5 <title>ligo.at</title> 6 6 <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 7 <link rel="stylesheet" href="{{ url_for('static', filename='inter.css') }}" /> 8 + <link rel="stylesheet" href="{{ url_for('static', filename='profile/default.css') }}" /> 8 9 <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" /> 9 10 <link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16.png') }}" /> 10 11 <link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-32.png') }}" /> ··· 30 31 <a href="{{ url_for('page_login') }}">login</a> 31 32 </p> 32 33 <footer> 33 - <p> 34 - <a href="https://tangled.org/@ligo.at/core" target="_blank">source code</a> 35 - <span>·</span> 36 - <a href="{{ url_for('page_terms') }}">terms of service</a> 37 - </p> 34 + {% include "_footerlinks.html" %} 38 35 <p> 39 36 Made by <a href="/@nauta.one">@nauta.one</a><br /> 40 37 </p>
+5 -5
src/templates/login.html
··· 5 5 <title>login &mdash; ligo.at</title> 6 6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /> 7 7 <link rel="stylesheet" href="{{ url_for('static', filename='inter.css') }}" /> 8 + <link rel="stylesheet" href="{{ url_for('static', filename='profile/default.css') }}" /> 8 9 <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" /> 9 10 <link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16.png') }}" /> 10 11 <link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-32.png') }}" /> ··· 28 29 <input type="submit" value="continue" /> 29 30 </form> 30 31 <footer> 31 - <a href="/">home</a> 32 - <span>·</span> 33 - <a href="{{ url_for('page_terms') }}">terms of service</a> 34 - <span>·</span> 35 - <a href="https://tangled.org/@ligo.at/core" target="_blank">source code</a> 32 + <p> 33 + <a href="/">home</a> 34 + </p> 35 + {% include "_footerlinks.html" %} 36 36 </footer> 37 37 </div> 38 38 <!-- .wrapper -->
+18 -16
src/templates/profile.html
··· 6 6 <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 7 <base target="_blank" /> 8 8 <link rel="stylesheet" href="{{ url_for('static', filename='inter.css') }}" /> 9 - <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" /> 9 + <link rel="stylesheet" href="{{ url_for('static', filename='profile/default.css') }}" /> 10 10 <link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16.png') }}" /> 11 11 <link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-32.png') }}" /> 12 12 <link rel="icon" type="image/png" sizes="48x48" href="{{ url_for('static', filename='favicon-48.png') }}" /> ··· 14 14 </head> 15 15 <body> 16 16 <div class="wrapper profile"> 17 - <header> 17 + <header class="links-header"> 18 18 <h1>{{ profile.displayName }}</h1> 19 19 {% if profile.description %} 20 20 <span class="tagline">{{ profile.description }}</span> 21 21 {% endif %} 22 22 </header> 23 - <ul> 24 - {% for link in links %} 25 - <li style="color: {{ link.backgroundColor }}"> 26 - <a href="{{ link.href }}"> 27 - <div class="link-item"> 28 - <span class="link-item-title">{{ link.title }}</span> 29 - {% if link.subtitle %} 30 - <span class="link-item-detail">{{ link.subtitle }}</span> 31 - {% endif %} 32 - </div><!-- .link-item --> 33 - </a> 34 - </li> 35 - {% endfor %} 36 - </ul> 23 + <div class="links-container"> 24 + <ul> 25 + {% for link in links %} 26 + <li style="color: {{ link.backgroundColor }}"> 27 + <a href="{{ link.href }}"> 28 + <div class="link-item"> 29 + <span class="link-item-title">{{ link.title }}</span> 30 + {% if link.subtitle %} 31 + <span class="link-item-detail">{{ link.subtitle }}</span> 32 + {% endif %} 33 + </div><!-- .link-item --> 34 + </a> 35 + </li> 36 + {% endfor %} 37 + </ul> 38 + </div> 37 39 <footer> 38 40 made with <a href="https://ligo.at" target="_self">ligo.at</a> 39 41 </footer>
+2 -3
src/templates/terms.html
··· 5 5 <title>terms of service &mdash; ligo.at</title> 6 6 <meta name="viewport" content="width=device-width, initial-scale=1" /> 7 7 <link rel="stylesheet" href="{{ url_for('static', filename='inter.css') }}" /> 8 + <link rel="stylesheet" href="{{ url_for('static', filename='profile/default.css') }}" /> 8 9 <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" /> 9 10 <link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16.png') }}" /> 10 11 <link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-32.png') }}" /> ··· 47 48 Engage in spam, phishing, or other deceptive practices. 48 49 Attempt to gain unauthorized access to the Service or other users' accounts. 49 50 Interfere with or disrupt the Service or servers connected to the Service. 50 - 51 51 </p> 52 52 53 53 <footer> 54 54 <p> 55 55 <a href="/">home</a> 56 - <span>·</span> 57 - <a href="https://tangled.org/@ligo.at/core" target="_blank">source code</a> 58 56 </p> 57 + {% include "_footerlinks.html" %} 59 58 </footer> 60 59 </div> 61 60 </body>