diff --git a/static/favicon.svg b/static/favicon.svg index 7d0bcf3..bce7842 100644 --- a/static/favicon.svg +++ b/static/favicon.svg @@ -1,5 +1,5 @@ - - e. + + + diff --git a/static/style.css b/static/style.css index 2abe1c9..5dfbcb6 100644 --- a/static/style.css +++ b/static/style.css @@ -1,124 +1,126 @@ +/* echoIRCd — the site as an IRC client. Monospace, warm phosphor, real IRC grammar. */ :root{ - --bg:#0b0e14; --bg2:#11161f; --bg3:#161c27; - --line:#222b38; --line2:#2b3646; - --fg:#c8d3e0; --fg2:#7d8896; --hi:#e6edf3; - --accent:#3fb950; --accent2:#2ea043; --link:#58a6ff; - --radius:12px; --wrap:1040px; - color-scheme:dark; + --bg:#08090c; --win:#0d0e12; --panel:#14161c; --panel2:#0f1116; + --edge:#22252e; --edge2:#2d313c; + --fg:#c8ccd4; --dim:#767b85; --dimmer:#4a4e58; + --amber:#e2a25a; --green:#5fbf6b; --blue:#5f9bef; --magenta:#c58af0; --cyan:#4fcccf; --red:#ec6d6d; + --link:#6aa6f2; --ok:#5fbf6b; + --mono:ui-monospace,"SF Mono","JetBrains Mono","Cascadia Code",Menlo,Consolas,"DejaVu Sans Mono",monospace; } *{box-sizing:border-box} -html{scroll-behavior:smooth} +html{-webkit-text-size-adjust:100%} body{ - margin:0; background:var(--bg); color:var(--fg); - font:16px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; + margin:0;background:var(--bg);color:var(--fg); + font:14.5px/1.65 var(--mono); + background-image:radial-gradient(1200px 600px at 50% -10%,rgba(226,162,90,.05),transparent 70%); -webkit-font-smoothing:antialiased; } -.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace} a{color:var(--link);text-decoration:none} a:hover{text-decoration:underline} -h1,h2,h3,h4{color:var(--hi);line-height:1.2} -.accent{color:var(--accent)} -main{min-height:60vh} -.wrap,.hero,.split,.page-head,.cs-in{max-width:var(--wrap);margin:0 auto;padding-left:1.25rem;padding-right:1.25rem} +b{color:var(--fg);font-weight:600} +.dim{color:var(--dim)} +.kw{color:var(--amber)} +.ok{color:var(--ok)} +.i{font-style:italic} +.n-amber{color:var(--amber)} .n-green{color:var(--green)} .n-blue{color:var(--blue)} +.n-magenta{color:var(--magenta)} .n-cyan{color:var(--cyan)} .n-red{color:var(--red)} -/* nav */ -.nav{ - display:flex;align-items:center;justify-content:space-between;gap:1rem; - max-width:var(--wrap);margin:0 auto;padding:1.1rem 1.25rem; -} -.brand{font-family:ui-monospace,monospace;font-weight:700;font-size:1.25rem;color:var(--hi)} -.brand:hover{text-decoration:none} -.brand .dot{color:var(--accent)} -.navlinks{display:flex;gap:1.4rem;align-items:center;flex-wrap:wrap} -.navlinks a{color:var(--fg2);font-size:.95rem} -.navlinks a:hover{color:var(--hi);text-decoration:none} -.navlinks a.on{color:var(--hi)} -.navlinks a.ext{color:var(--fg2)} - -/* hero */ -.hero{padding:3.5rem 1.25rem 2rem;text-align:center} -.badge-row{display:flex;gap:.5rem;justify-content:center;flex-wrap:wrap;margin-bottom:1.6rem} -.badge{ - font-size:.78rem;color:var(--accent);background:rgba(63,185,80,.08); - border:1px solid rgba(63,185,80,.28);border-radius:999px;padding:.25rem .7rem; -} -.hero h1{font-size:clamp(2.1rem,5vw,3.4rem);letter-spacing:-1.5px;margin:.2rem 0 1rem} -.lede{color:var(--fg2);font-size:1.12rem;max-width:640px;margin:0 auto 1.8rem} -.cta{display:flex;gap:.8rem;justify-content:center;flex-wrap:wrap} -.btn{ - display:inline-block;padding:.65rem 1.2rem;border-radius:8px;font-weight:600; - border:1px solid var(--line2);color:var(--hi);background:var(--bg2); -} -.btn:hover{border-color:#3a475a;text-decoration:none} -.btn.primary{background:var(--accent2);border-color:var(--accent);color:#04120a} -.btn.primary:hover{background:var(--accent)} -.connectline{ - margin:1.8rem auto 0;max-width:max-content;color:var(--accent); - background:var(--bg2);border:1px solid var(--line);border-radius:8px;padding:.55rem 1rem;font-size:.95rem; +/* the client window */ +.client{ + max-width:1060px;margin:1.6rem auto;background:var(--win); + border:1px solid var(--edge);border-radius:9px;overflow:hidden; + box-shadow:0 24px 60px -30px rgba(0,0,0,.8),0 0 0 1px rgba(255,255,255,.01); } -/* split cards */ -.split{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-top:1.5rem} -.card{background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius);padding:1.4rem 1.5rem} -.card h3{margin:0 0 .5rem;font-size:1.25rem} -.card p{margin:0;color:var(--fg2)} -.tag{font-size:.7rem;text-transform:uppercase;letter-spacing:.1em;color:var(--fg2); - border:1px solid var(--line2);border-radius:6px;padding:.1rem .45rem;margin-left:.4rem;vertical-align:middle} +/* title bar */ +.titlebar{display:flex;align-items:center;gap:.6rem;padding:.55rem .9rem;background:var(--panel);border-bottom:1px solid var(--edge)} +.conn{width:9px;height:9px;border-radius:50%;background:var(--green);box-shadow:0 0 8px var(--green);flex:none} +.tb-name{color:var(--fg);font-weight:600} +.tb-server{margin-left:auto;color:var(--dim);font-size:.82rem} -/* feature grid */ -.wrap{padding-top:3.5rem;padding-bottom:1rem} -.section-title{text-align:center;font-size:1.6rem;margin:0 0 2rem} -.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem} -.feat{background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius);padding:1.3rem 1.4rem} -.feat .ico{font-size:1.5rem;margin-bottom:.5rem} -.feat h4{margin:.1rem 0 .5rem;font-size:1.08rem} -.feat p{margin:0;color:var(--fg2);font-size:.95rem} -.feat em{color:var(--fg);font-style:normal;font-weight:600} +/* tabs */ +.tabs{display:flex;gap:.15rem;padding:0 .5rem;background:var(--panel);border-bottom:1px solid var(--edge);overflow-x:auto} +.tab{padding:.5rem .8rem;color:var(--dim);border-bottom:2px solid transparent;white-space:nowrap} +.tab:hover{color:var(--fg);text-decoration:none} +.tab.on{color:var(--amber);border-bottom-color:var(--amber)} +.tab.ext{margin-left:auto;color:var(--dimmer)} -/* connect strip */ -.connect-strip{margin:4rem 0 0;background:linear-gradient(180deg,var(--bg2),var(--bg3));border-top:1px solid var(--line)} -.cs-in{display:flex;align-items:center;justify-content:space-between;gap:1.5rem;padding:2.4rem 1.25rem;flex-wrap:wrap} -.cs-in h2{margin:0 0 .2rem;font-size:1.5rem} -.cs-in p{margin:0;color:var(--fg2)} -.mini{border-collapse:collapse;font-size:.95rem} -.mini td{padding:.28rem .9rem;border-bottom:1px solid var(--line)} -.mini td:first-child{color:var(--fg2)} +/* topic */ +.topic{padding:.5rem .95rem;background:var(--panel2);border-bottom:1px solid var(--edge);color:var(--dim);font-size:.85rem} +.topic .tp{color:var(--amber);margin-right:.35rem} -/* pages */ -.page-head{padding:3rem 1.25rem 1rem;text-align:center} -.page-head h1{font-size:2.4rem;letter-spacing:-1px;margin:0 0 .6rem} -.prose .block{margin:0 0 2.2rem} -.block h2{font-size:1.35rem;border-bottom:1px solid var(--line);padding-bottom:.5rem;margin:0 0 .9rem} -.block ul{margin:.4rem 0 0;padding-left:1.1rem} -.block li{margin:.35rem 0;color:var(--fg2)} -.block li strong{color:var(--fg)} +/* workspace = buffer + nicklist */ +.workspace{display:flex;align-items:stretch} +.buffer{flex:1;min-width:0;padding:1.1rem 1.1rem 1.4rem} +.nicklist{width:13.5rem;flex:none;background:var(--panel2);border-left:1px solid var(--edge);padding:1rem .85rem;font-size:.86rem} +.nl-head{color:var(--dim);text-transform:uppercase;letter-spacing:.12em;font-size:.72rem;margin-bottom:.6rem} +.nicklist ul{list-style:none;margin:0;padding:0} +.nicklist li{display:flex;align-items:center;gap:.15rem;padding:.14rem 0;white-space:nowrap} +.nicklist .s{display:inline-block;width:1.1em;text-align:center;color:var(--dim)} +.bf{margin-left:.35rem;font-size:.62rem;color:var(--dimmer);border:1px solid var(--edge2);border-radius:3px;padding:0 .25em} -/* chips */ -.chips{display:flex;flex-wrap:wrap;gap:.4rem;margin-top:.6rem} -.chips span{ - font-family:ui-monospace,monospace;font-size:.8rem;color:var(--fg); - background:var(--bg3);border:1px solid var(--line);border-radius:6px;padding:.2rem .5rem; -} - -/* tables + code on connect page */ -.detail{width:100%;border-collapse:collapse;margin:.5rem 0 1rem} -.detail th{text-align:left;color:var(--fg2);font-weight:500;padding:.5rem .9rem;border-bottom:1px solid var(--line);white-space:nowrap;vertical-align:top} -.detail td{padding:.5rem .9rem;border-bottom:1px solid var(--line);color:var(--fg)} -.code{ - background:var(--bg2);border:1px solid var(--line);border-radius:8px; - padding:1rem 1.1rem;overflow-x:auto;color:var(--accent); - font-family:ui-monospace,monospace;font-size:.9rem;line-height:1.7;white-space:pre; -} -.hint{color:var(--fg2);font-size:.92rem} -.webchat{display:flex;align-items:center;gap:1rem;flex-wrap:wrap;margin:1.5rem 0 0;color:var(--fg2)} - -/* footer */ -.foot{border-top:1px solid var(--line);margin-top:4rem} -.foot-in{max-width:var(--wrap);margin:0 auto;padding:1.6rem 1.25rem;display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;color:var(--fg2);font-size:.9rem} -.foot .mono{color:var(--fg)} -.foot-links{display:flex;gap:1.1rem} - -@media(max-width:760px){ - .split{grid-template-columns:1fr} - .grid{grid-template-columns:1fr} +/* buffer lines — [time] [gutter] [message] */ +.ln{display:grid;grid-template-columns:3.1em 7em 1fr;column-gap:.75em;align-items:baseline;padding:.09rem 0} +.ln .t{color:var(--dimmer);font-size:.82em} +.ln .g{text-align:right;white-space:nowrap;color:var(--dim)} +.ln .m{min-width:0;word-wrap:break-word;overflow-wrap:anywhere} +.ln .m a{color:var(--link)} + +/* banner / wordmark */ +.banner{padding:.6rem 0 1.4rem;border-bottom:1px dashed var(--edge);margin-bottom:1rem} +.wordmark{font-size:clamp(2.3rem,7vw,3.7rem);font-weight:700;letter-spacing:-2px;color:var(--fg);line-height:1} +.wordmark .w-hi{color:var(--amber)} +.w-sub{color:var(--dim);margin-top:.5rem;font-size:.95rem} +.cur{display:inline-block;width:.55em;color:var(--amber);animation:blink 1.1s steps(1) infinite} +.cur-lg{width:.5em;margin-left:.06em} +@keyframes blink{50%{opacity:0}} +@media(prefers-reduced-motion:reduce){.cur{animation:none}} + +/* quickfacts */ +.quickfacts{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.3rem} +.qf{border:1px solid var(--edge);border-radius:6px;padding:.4rem .7rem;color:var(--dim);background:var(--panel2);font-size:.85rem} +.qf:hover{border-color:var(--edge2);color:var(--fg);text-decoration:none} +.qf .qf-k{color:var(--amber)} + +/* feature groups */ +.grp{margin:1.5rem 0} +.grp-h{color:var(--amber);font-size:.82rem;text-transform:uppercase;letter-spacing:.14em;padding-bottom:.4rem;margin-bottom:.7rem;border-bottom:1px solid var(--edge);position:relative} +.grp-h::before{content:"── ";color:var(--dimmer)} +.bul{list-style:none;margin:0;padding:0} +.bul li{padding:.22rem 0 .22rem 1.3em;position:relative;color:var(--fg)} +.bul li::before{content:"·";position:absolute;left:.3em;color:var(--amber)} +.srvline{display:grid;grid-template-columns:7em 1fr;column-gap:.75em;align-items:baseline;margin:.2rem 0 .8rem} +.srvline .g{text-align:right} +.capline{color:var(--dim);word-break:break-word;line-height:1.7} + +/* connect page: tables + code */ +.detail{width:100%;border-collapse:collapse;margin:.7rem 0 1rem;font-size:.9rem} +.detail th{text-align:left;color:var(--dim);font-weight:400;padding:.4rem .8rem .4rem 0;border-bottom:1px solid var(--edge);white-space:nowrap;vertical-align:top;width:1%} +.detail td{padding:.4rem 0;border-bottom:1px solid var(--edge);color:var(--fg)} +.note{color:var(--dim);margin:.2rem 0 .6rem;font-size:.9rem} +.code{background:var(--panel2);border:1px solid var(--edge);border-left:2px solid var(--amber);border-radius:6px; + padding:.8rem 1rem;overflow-x:auto;color:var(--green);font-size:.88rem;line-height:1.75;white-space:pre;margin:.4rem 0} +.webchat{display:flex;align-items:center;gap:.8rem;flex-wrap:wrap;margin:1.1rem 0} +.btn{display:inline-block;border:1px solid var(--edge2);background:var(--panel);color:var(--fg);padding:.4rem .85rem;border-radius:6px;font-size:.88rem} +.btn:hover{border-color:var(--amber);color:var(--amber);text-decoration:none} + +/* input + status bars */ +.inputbar{display:flex;align-items:baseline;gap:.5rem;padding:.55rem .95rem;background:var(--panel);border-top:1px solid var(--edge);font-size:.9rem;overflow:hidden} +.ib-ch{color:var(--dim)} +.ib-prompt{color:var(--amber)} +.ib-text{color:var(--fg);white-space:nowrap;overflow:hidden;text-overflow:ellipsis} +.statusbar{display:flex;align-items:center;gap:.8rem;padding:.4rem .95rem;background:var(--panel2);border-top:1px solid var(--edge);font-size:.74rem;color:var(--dim)} +.statusbar .sb-m{margin:0 auto;color:var(--amber);opacity:.75} +.statusbar a{color:var(--dim)} +.statusbar a:hover{color:var(--fg)} + +@media(max-width:720px){ + .client{margin:0;border:0;border-radius:0;min-height:100vh} + .workspace{flex-direction:column} + .nicklist{width:auto;border-left:0;border-top:1px solid var(--edge);order:2} + .nicklist ul{display:flex;flex-wrap:wrap;gap:.1rem .9rem} + .ln{grid-template-columns:5.5em 1fr} + .ln .t{display:none} + .srvline{grid-template-columns:5.5em 1fr} + .tb-server{display:none} } diff --git a/templates/base.html b/templates/base.html index 3e245c0..9eb6f3d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -3,38 +3,67 @@ + {% block title %}echoIRCd{% endblock %} - + - + - +
-
-{% block content %}{% endblock %} -
- - + + + +
» {% block topic %}echoIRCd — a native-Rust IRC daemon & services{% endblock %}
+ +
+
+ {% block buffer %}{% endblock %} +
+ +
+ +
+ [{% block chan %}#home{% endblock %}] + + {% block cmd %}/connect{% endblock %} +
+ +
+ echoIRCd 5.0.0 + #![forbid(unsafe_code)] + services · website +
+ +
diff --git a/templates/connect.html b/templates/connect.html index 0efb687..5f12a80 100644 --- a/templates/connect.html +++ b/templates/connect.html @@ -1,58 +1,54 @@ {% extends "base.html" %} -{% block title %}Connect — echoIRCd{% endblock %} -{% block content %} -
-

Connect

-

Point any IRC client at the network — or open it in your browser.

-
+{% block title %}#connect — echoIRCd{% endblock %} +{% block topic %}#connect — point any client at irc.echoircd.org, or use the browser{% endblock %} +{% block chan %}#connect{% endblock %} +{% block cmd %}/server irc.echoircd.org +6697{% endblock %} +{% block buffer %} +
19:33<you>/server irc.echoircd.org +6697
+
19:33-!-connecting to irc.echoircd.org:6697 … TLS1.3 up (X25519MLKEM768)
+
19:33-!-Welcome to the echoiRCd IRC Network
-
- - - - + + + +
Serverirc.echoircd.org
TLS (recommended)6697
Plaintext6667
NetworkechoiRCd
serverirc.echoircd.org
tls (recommended)6697
plaintext6667
networkechoiRCd
- Prefer the browser? - Open the web client ↗ + prefer the browser? + open the web client ↗
-

Client quick-start

-
-

Most clients accept a one-line server string. The leading + on the - port means TLS.

+
+
client quick-start
+

most clients take a one-line server string; the leading + means TLS.

/server irc.echoircd.org +6697
 /join #echoircd
- - - - + + + +
HexChatNetwork list → Add → irc.echoircd.org/+6697 → tick "Use SSL"
WeeChat/server add echo irc.echoircd.org/6697 -tls
irssi/connect -tls irc.echoircd.org 6697
mIRC/server irc.echoircd.org +6697
HexChatadd irc.echoircd.org/+6697 · tick “Use SSL”
WeeChat/server add echo irc.echoircd.org/6697 -tls
irssi/connect -tls irc.echoircd.org 6697
mIRC/server irc.echoircd.org +6697
-

Register your nick

-
-

Registering lets you keep your nickname, found channels, and log in with SASL.

+
+
register your nick
+

keep your nick, found channels, and log in with SASL.

/msg NickServ REGISTER <password> <email>
 /msg NickServ IDENTIFY <password>
-

Log in with a key (ECDSA)

-
-

Instead of a password you can authenticate with a NIST P-256 key. The server sends a - challenge, your client signs it, and the signature is checked against the key on your - account — nothing secret crosses the wire.

-
# generate a key and read its public half
+  
+
log in with a key (ecdsa)
+

sign a server challenge with a NIST P-256 key instead of sending a password — nothing secret crosses the wire.

+
# generate a key, read its public half
 ecdsatool keygen ~/.ecdsa.pem
 ecdsatool pubkey ~/.ecdsa.pem
 
-# store it on your account, then use ECDSA-NIST256P-CHALLENGE for SASL
+# store it, then pick ECDSA-NIST256P-CHALLENGE for SASL
 /msg NickServ SET PUBKEY <printed-public-key>
-

Point your client's SASL settings at the same key file and pick the - ECDSA-NIST256P-CHALLENGE mechanism.

+

point your client's SASL settings at the same key file.

-
{% endblock %} diff --git a/templates/features.html b/templates/features.html index be9012d..6aaed2f 100644 --- a/templates/features.html +++ b/templates/features.html @@ -1,85 +1,66 @@ {% extends "base.html" %} -{% block title %}Features — echoIRCd{% endblock %} -{% block content %} -
-

Features

-

Everything below is original, native Rust — the InspIRCd protocol and API are a - reference for wire compatibility, never a source of code.

-
+{% block title %}#features — echoIRCd{% endblock %} +{% block topic %}#features — what's inside the daemon & services{% endblock %} +{% block chan %}#features{% endblock %} +{% block cmd %}/msg echoircd help{% endblock %} +{% block buffer %} +
19:31<you>/msg echoircd what can you do
+
19:31<echoircd>plenty — here's the short tour. all of it is original, native Rust.
-
-
-

The daemon

-
-
-
-

Ready?

See how to connect and register.

- Connect & register -
-
+
19:32*echoircd nods toward #connect
{% endblock %} diff --git a/templates/index.html b/templates/index.html index 30a6b36..e17e782 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,93 +1,28 @@ {% extends "base.html" %} -{% block title %}echoIRCd — a modern IRC network in Rust{% endblock %} -{% block content %} -
-
- 100% safe Rust - TLS 1.3 · post-quantum - Full IRCv3 - SASL +{% block title %}echoIRCd — a native-Rust IRC network{% endblock %} +{% block topic %}#home — echoIRCd, a native-Rust IRC daemon & services · no fork · no C · no unsafe{% endblock %} +{% block chan %}#home{% endblock %} +{% block cmd %}/connect{% endblock %} +{% block buffer %} + -

A modern IRC network,
built from scratch in Rust.

-

echoIRCd is an original IRC daemon and services suite — no forks, no C, no - unsafe. Full IRCv3, modern TLS, server-to-server linking, and a - complete services stack with accounts, channels, and SASL.

- -
/server irc.echoircd.org +6697
-
-
-
-

echoIRCd the daemon

-

A single-threaded core with an epoll reactor pool and a module-per-file architecture. - The full channel and user mode set, host cloaking, connection classes, PROXY protocol, - ident, and an InspIRCd-style operator privilege system.

-
-
-

echo the services

-

NickServ, ChanServ, OperServ, MemoServ and more, linked over a standard server-to-server - protocol. Account registration, vhosts, grouped nicks, memos and SASL — all backed by an - event-sourced store.

-
-
+
19:28-!-Now talking on #home
+
19:28-!-echoIRCd/5.0.0 · irc.echoircd.org · network echoiRCd · +6697 TLS1.3
+
19:28-->you (~guest@echoircd.org) has joined #home
+
19:29<echoircd>hey — you're looking at an IRC network written from the ground up in Rust.
+
19:29<echoircd>original code: no InspIRCd fork, no C, and #![forbid(unsafe_code)] across the whole tree.
+
19:29<echoircd>the daemon speaks full IRCv3 and modern TLS; services handle accounts, channels and SASL.
+
19:30*echoircd slides the tabs your way — #features for the tech, #connect to join
+
19:30<you>nice. how do I get on?
+
19:30<echoircd>/connect — or open the web client right in your browser.
-
-

What's inside

-
-
-
🔒
-

Modern TLS

-

Direct TLS on 6697 and WebSocket (wss) on 7799. OpenSSL and rustls backends, - TLS 1.3 with post-quantum X25519MLKEM768, and per-host SNI certificates.

-
-
-
-

Full IRCv3

-

server-time, message-tags, account-tag, extended-join, batch, labeled-response, - chathistory, multiline, setname, standard-replies, metadata and more.

-
-
-
🔑
-

SASL

-

PLAIN, EXTERNAL (certificate fingerprint), SCRAM-SHA-256, and - ECDSA-NIST256P-CHALLENGE — sign a challenge with your key, no password on the wire.

-
-
-
🤖
-

Services

-

Accounts, channels, vhosts, memos and games over a standard S2S link, with SASL relayed - mechanism-agnostically to the services layer.

-
-
-
🛡
-

Anti-abuse

-

A native security subsystem: connection and nick-flood detection, behavioral and content - heuristics, DEFCON states, and DNSBL / MX screening.

-
-
-
🌐
-

Localized

-

Server-wide locale catalogs translate numerics and service replies at a single chokepoint. - English stays zero-cost; switch locales on rehash.

-
+ -
- -
-
-
-

Jump in.

-

Point any IRC client at the network and say hello.

-
- - - - - -
Serverirc.echoircd.org
TLS6697
WebSocket7799 (wss)
NetworkechoiRCd
-
-
{% endblock %}