refactor: move navbar and footer to layout.tsx

This commit is contained in:
Konstantin Zhigaylo 2025-07-01 15:40:10 +03:00
parent c52e971b36
commit 66b780eaad
No known key found for this signature in database
GPG Key ID: DD1C2780F0E05B5C
8 changed files with 394 additions and 449 deletions

2
.gitignore vendored
View File

@ -39,3 +39,5 @@ yarn-error.log*
# typescript # typescript
*.tsbuildinfo *.tsbuildinfo
next-env.d.ts next-env.d.ts
/.idea

View File

@ -1,6 +1,8 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Geist, Rokkitt } from "next/font/google"; import { Geist, Rokkitt } from "next/font/google";
import "./globals.css"; import "./globals.css";
import NavBar from "@/components/NavBar";
import Footer from "@/components/Footer";
const geistSans = Geist({ const geistSans = Geist({
variable: "--font-geist", variable: "--font-geist",
@ -25,9 +27,11 @@ export default function RootLayout({
return ( return (
<html lang="en"> <html lang="en">
<body <body
className={`${geistSans.variable} ${rokkitt.variable} bg-stone-900 font-geist antialiased`} className={`${geistSans.variable} ${rokkitt.variable} flex flex-col gap-4 bg-stone-900 font-geist antialiased max-w-[700px] mx-auto p-4 pt-15`}
> >
<NavBar />
{children} {children}
<Footer />
</body> </body>
</html> </html>
); );

View File

@ -1,25 +1,17 @@
import NavBar from "@/components/NavBar";
import Footer from "@/components/Footer";
import Text from "@/components/blocks/Text"; import Text from "@/components/blocks/Text";
export default function Home() { export default function Home() {
return ( return (
<div className={"bg-stone-900 min-h-screen font-geist"}> <main className={"flex flex-col gap-4 mx-auto w-full"}>
<main
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
>
<NavBar />
<Text> <Text>
Welcome to an unofficial webpage about the Real Address Chat protocol. Welcome to an unofficial webpage about the Real Address Chat protocol.
Here you can find clients, servers, and documentation on how to use Here you can find clients, servers, and documentation on how to use RAC
RAC and its successor, WRAC. and its successor, WRAC.
</Text> </Text>
<Text> <Text>
Want to add your project to Racinfo? Make a pull request on our Want to add your project to Racinfo? Make a pull request on our official
official GitHub repository, and well review it. GitHub repository, and well review it.
</Text> </Text>
<Footer />
</main> </main>
</div>
); );
} }

View File

@ -43,13 +43,6 @@ export default function Projects() {
description: "Coming Soon™", description: "Coming Soon™",
tags: ["Unreleased", "WRAC", "RAC", "v2"], tags: ["Unreleased", "WRAC", "RAC", "v2"],
}, },
{
name: "oWRAC",
authorId: "pansangg",
projectGit: "https://github.com/pansangg/oWRAC",
description: "An online WRAC client (works in web)",
tags: ["Unreleased", "WRAC", "v2"],
},
{ {
name: "clRAC", name: "clRAC",
externalDownload: true, externalDownload: true,
@ -116,17 +109,13 @@ export default function Projects() {
]; ];
return ( return (
<div className={"bg-stone-900 min-h-screen font-geist"}> <main className={"flex flex-col gap-4 w-full"}>
<main
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
>
<NavBar />
<PageTitle id={"projects"}>Projects</PageTitle> <PageTitle id={"projects"}>Projects</PageTitle>
<Text> <Text>
This is a curated list of projects that is related to RAC protocol. This is a curated list of projects that is related to RAC protocol.
There is a client and server implementations of RAC. Note that some There is a client and server implementations of RAC. Note that some
projects are not available on Git services and should be downloaded projects are not available on Git services and should be downloaded from
from external sources. They are marked with external sources. They are marked with
<InlineCode>external@</InlineCode> text at the beginning of the author <InlineCode>external@</InlineCode> text at the beginning of the author
ID. If you want to add your project to this list, please make an issue ID. If you want to add your project to this list, please make an issue
on our GitHub repository. on our GitHub repository.
@ -169,8 +158,6 @@ export default function Projects() {
/> />
))} ))}
</div> </div>
<Footer />
</main> </main>
</div>
); );
} }

View File

@ -1,24 +1,18 @@
import NavBar from "@/components/NavBar"; import Link from "next/link";
import Footer from "@/components/Footer";
import Link from "next/link";
import Text from "@/components/blocks/Text"; import Text from "@/components/blocks/Text";
import PageTitle from "@/components/blocks/PageTitle"; import PageTitle from "@/components/blocks/PageTitle";
import Title from "@/components/blocks/Title"; import Title from "@/components/blocks/Title";
export default function Protocol() { export default function Protocol() {
return ( return (
<div className={"bg-stone-900 min-h-screen font-geist"}> <main className={"flex flex-col gap-4 w-full"}>
<main
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
>
<NavBar />
<PageTitle id={"protocol"}>Protocol</PageTitle> <PageTitle id={"protocol"}>Protocol</PageTitle>
<Text> <Text>
Real Address Chat is a protocol based on TCP intended for chatting, Real Address Chat is a protocol based on TCP intended for chatting, like
like IRC. It was supposed to be an IRC killer, but in reality, its IRC. It was supposed to be an IRC killer, but in reality, its
implementation is poor. Theres also a community-made successor called implementation is poor. Theres also a community-made successor called
WRAC. Its basically the same as RAC, but it uses WebSockets instead WRAC. Its basically the same as RAC, but it uses WebSockets instead of
of TCP for connections. TCP for connections.
</Text> </Text>
<Text> <Text>
If you want to experiment with or implement RAC in your client or If you want to experiment with or implement RAC in your client or
@ -68,14 +62,12 @@ export default function Protocol() {
User Agents User Agents
</h1> </h1>
<p className={"text-stone-500"}> <p className={"text-stone-500"}>
A community-made solution to identify clients by a unique symbol A community-made solution to identify clients by a unique symbol in
in front of their username. front of their username.
</p> </p>
<small className={"text-stone-600"}>Curated by @kostya-zero</small> <small className={"text-stone-600"}>Curated by @kostya-zero</small>
</Link> </Link>
</div> </div>
<Footer />
</main> </main>
</div>
); );
} }

View File

@ -1,6 +1,4 @@
import NavBar from "@/components/NavBar"; import { ArrowLeft } from "lucide-react";
import Footer from "@/components/Footer";
import { ArrowLeft } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { import {
Table, Table,
@ -18,11 +16,7 @@ import Code from "@/components/blocks/Code";
export default function Rac() { export default function Rac() {
return ( return (
<div className={"bg-stone-900 min-h-screen font-geist"}> <main className={"flex flex-col gap-4 w-full"}>
<main
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
>
<NavBar />
<Link <Link
href={"/protocol"} href={"/protocol"}
className={ className={
@ -40,8 +34,8 @@ export default function Rac() {
implementation is pretty simple, so dont worry. implementation is pretty simple, so dont worry.
</Text> </Text>
<Text> <Text>
All RAC servers use port <InlineCode>42666</InlineCode> by default, All RAC servers use port <InlineCode>42666</InlineCode> by default, but
but servers that implement RACS (Real Address Chat Secure) use port{" "} servers that implement RACS (Real Address Chat Secure) use port{" "}
<InlineCode>42667</InlineCode>. <InlineCode>42667</InlineCode>.
</Text> </Text>
<Text> <Text>
@ -56,8 +50,8 @@ export default function Rac() {
</Text> </Text>
<Text> <Text>
But before you try to receive new messages, you need to get the total But before you try to receive new messages, you need to get the total
size of all messages. The messages are stored on the server in a size of all messages. The messages are stored on the server in a single
single file, and to get new messages, you should send an offset. file, and to get new messages, you should send an offset.
</Text> </Text>
<Text> <Text>
To receive the current size of the messages on the server, you need to To receive the current size of the messages on the server, you need to
@ -67,38 +61,37 @@ export default function Rac() {
</Text> </Text>
<Text> <Text>
The first way is to receive all messages stored on the server. The The first way is to receive all messages stored on the server. The
client should send a <InlineCode>0x00</InlineCode> byte and then, in client should send a <InlineCode>0x00</InlineCode> byte and then, in the
the same stream, send a <InlineCode>0x01</InlineCode> byte to the same stream, send a <InlineCode>0x01</InlineCode> byte to the server.
server. The server will respond with all messages, separated by{" "} The server will respond with all messages, separated by{" "}
<InlineCode>\n</InlineCode>. <InlineCode>\n</InlineCode>.
</Text> </Text>
<Text> <Text>
The second way is to get messages in chunks. Again, the client sends a{" "} The second way is to get messages in chunks. Again, the client sends a{" "}
<InlineCode>0x00</InlineCode> byte and then sends a{" "} <InlineCode>0x00</InlineCode> byte and then sends a{" "}
<InlineCode>0x02</InlineCode> byte, along with the size of the <InlineCode>0x02</InlineCode> byte, along with the size of the messages
messages it wants to receive. The number of messages to receive is it wants to receive. The number of messages to receive is calculated
calculated using this formula: using this formula:
</Text> </Text>
<Code>new_received_size - last_known_size</Code> <Code>new_received_size - last_known_size</Code>
<Text> <Text>
The server will send messages matching the requested size, separated The server will send messages matching the requested size, separated by{" "}
by <InlineCode>\n</InlineCode>. <InlineCode>\n</InlineCode>.
</Text> </Text>
<Title id={"sending-messages"}>Sending messages</Title> <Title id={"sending-messages"}>Sending messages</Title>
<Text> <Text>
Sending messages in RAC is implemented simply, but with some Sending messages in RAC is implemented simply, but with some interesting
interesting details. The server doesnt identify clients or users, so details. The server doesnt identify clients or users, so clients have
clients have to handle that themselves. This means the client must to handle that themselves. This means the client must send the user
send the user agent, username, and message all in one packet. For agent, username, and message all in one packet. For example:
example:
</Text> </Text>
<Code>{"▲<zero> Hello, world!"}</Code> <Code>{"▲<zero> Hello, world!"}</Code>
<Text> <Text>
Did you notice the <InlineCode></InlineCode> symbol? This is called a Did you notice the <InlineCode></InlineCode> symbol? This is called a
User Agent. In this example, the message was sent by the Tower client, User Agent. In this example, the message was sent by the Tower client,
because <InlineCode></InlineCode> is its respective user agent. As because <InlineCode></InlineCode> is its respective user agent. As
mentioned earlier, the server itself cannot identify clients, so mentioned earlier, the server itself cannot identify clients, so clients
clients have to identify each other using these user agents. have to identify each other using these user agents.
</Text> </Text>
<Text> <Text>
Also, note that <InlineCode>zero</InlineCode> is wrapped inside{" "} Also, note that <InlineCode>zero</InlineCode> is wrapped inside{" "}
@ -107,18 +100,18 @@ export default function Rac() {
own in the user agents article. own in the user agents article.
</Text> </Text>
<Text> <Text>
Note that the server should store the IP address with each sent Note that the server should store the IP address with each sent message.
message. However, messages sent by clients in authorized mode should However, messages sent by clients in authorized mode should be ignored
be ignored for this. This idea, introduced by Sugoma, means that for this. This idea, introduced by Sugoma, means that clients shouldnt
clients shouldnt be anonymous unless theyre authorized. Still, most be anonymous unless theyre authorized. Still, most clients ignore the
clients ignore the IP address and dont display it. IP address and dont display it.
</Text> </Text>
<Text> <Text>
Back to sending messages: To send a message to the server, the client Back to sending messages: To send a message to the server, the client
should send a <InlineCode>0x01</InlineCode> byte, followed by the should send a <InlineCode>0x01</InlineCode> byte, followed by the
message in the same packetnot separately. After that, you wont message in the same packetnot separately. After that, you wont receive
receive anything from the server, even if theres an error. So your anything from the server, even if theres an error. So your final
final message should look like this: message should look like this:
</Text> </Text>
<Code>{"<user> Hello, everyone!"}</Code> <Code>{"<user> Hello, everyone!"}</Code>
<Text> <Text>
@ -126,30 +119,28 @@ export default function Rac() {
authorized mode. To send message in authorized mode, you need to send{" "} authorized mode. To send message in authorized mode, you need to send{" "}
<InlineCode>0x02</InlineCode> and after that, separating by{" "} <InlineCode>0x02</InlineCode> and after that, separating by{" "}
<InlineCode>\n</InlineCode>, send user&apos;s user name, password and <InlineCode>\n</InlineCode>, send user&apos;s user name, password and
message (<b>do not</b> include <InlineCode>\n</InlineCode> in the message (<b>do not</b> include <InlineCode>\n</InlineCode> in the end).
end).
</Text> </Text>
<Text> <Text>
If the message was sent successfully, the server wont send any If the message was sent successfully, the server wont send any
response. If not, the server will send a <InlineCode>0x01</InlineCode>{" "} response. If not, the server will send a <InlineCode>0x01</InlineCode>{" "}
byte if the user doesnt exist, and a <InlineCode>0x02</InlineCode>{" "} byte if the user doesnt exist, and a <InlineCode>0x02</InlineCode> byte
byte if the password is incorrect. if the password is incorrect.
</Text> </Text>
<Title id={"authorization"}>Authorization</Title> <Title id={"authorization"}>Authorization</Title>
<Text> <Text>
Authorization is only available on servers that implement the RAC v2 Authorization is only available on servers that implement the RAC v2
protocol, which adds an authorization system. This feature was added protocol, which adds an authorization system. This feature was added by
by Sugoma for people who dont want to expose their IP address to Sugoma for people who dont want to expose their IP address to everyone.
everyone.
</Text> </Text>
<Text> <Text>
Before sending messages in authorized mode, you need to register a Before sending messages in authorized mode, you need to register a user
user on the server. To do this, the client should send a{" "} on the server. To do this, the client should send a{" "}
<InlineCode>0x03</InlineCode> byte and, just like when sending <InlineCode>0x03</InlineCode> byte and, just like when sending messages,
messages, include the username and password separated by{" "} include the username and password separated by{" "}
<InlineCode>\n</InlineCode>. If the user is created, the client will <InlineCode>\n</InlineCode>. If the user is created, the client will
receive nothing in response. If the user already exists, the server receive nothing in response. If the user already exists, the server will
will respond with a <InlineCode>0x01</InlineCode> byte. respond with a <InlineCode>0x01</InlineCode> byte.
</Text> </Text>
<Title id={"tls-connection"}>TLS Connection</Title> <Title id={"tls-connection"}>TLS Connection</Title>
<Text> <Text>
@ -162,10 +153,9 @@ export default function Rac() {
dont add much functionality. dont add much functionality.
</Text> </Text>
<Text> <Text>
One of them is the <InlineCode>0x69</InlineCode> byte. You can send One of them is the <InlineCode>0x69</InlineCode> byte. You can send this
this byte to the server to get technical information about it. For byte to the server to get technical information about it. For example,
example, after sending this byte, you might receive these bytes in after sending this byte, you might receive these bytes in response:
response:
</Text> </Text>
<Table> <Table>
<TableHeader> <TableHeader>
@ -199,8 +189,6 @@ export default function Rac() {
Also, right after this byte, the server will send information about Also, right after this byte, the server will send information about
itself, such as the server software name and its version. itself, such as the server software name and its version.
</Text> </Text>
<Footer />
</main> </main>
</div>
); );
} }

View File

@ -1,6 +1,4 @@
import NavBar from "@/components/NavBar"; import { ArrowLeft } from "lucide-react";
import Footer from "@/components/Footer";
import { ArrowLeft } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { import {
Table, Table,
@ -60,11 +58,7 @@ export default function Wrac() {
}, },
]; ];
return ( return (
<div className={"bg-stone-900 min-h-screen font-geist"}> <main className={"flex flex-col gap-4 w-full"}>
<main
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
>
<NavBar />
<Link <Link
href={"/protocol"} href={"/protocol"}
className={ className={
@ -75,21 +69,21 @@ export default function Wrac() {
</Link> </Link>
<PageTitle id={"user-agents"}>User Agents</PageTitle> <PageTitle id={"user-agents"}>User Agents</PageTitle>
<Text> <Text>
The RAC protocol doesnt have any functionality to identify clients, The RAC protocol doesnt have any functionality to identify clients, so
so the community decided to use their own solution called{" "} the community decided to use their own solution called{" "}
<b>User Agents</b>. <b>User Agents</b>.
</Text> </Text>
<Text> <Text>
User Agents in RAC are implemented by adding an extra Unicode symbol User Agents in RAC are implemented by adding an extra Unicode symbol as
as a prefix to usernames. For example, a message sent with the Tower a prefix to usernames. For example, a message sent with the Tower
client: client:
</Text> </Text>
<Code>{"▲<zero> Hello, world!"}</Code> <Code>{"▲<zero> Hello, world!"}</Code>
<Text> <Text>
The <InlineCode></InlineCode> symbol in front of the username The <InlineCode></InlineCode> symbol in front of the username indicates
indicates that this message was sent using the Tower client. The that this message was sent using the Tower client. The client should use
client should use regex to parse these messages and determine the regex to parse these messages and determine the client, username, and
client, username, and message. message.
</Text> </Text>
<h3 className={"text-3xl text-stone-300 font-semibold font-rokkitt"}> <h3 className={"text-3xl text-stone-300 font-semibold font-rokkitt"}>
Known Agents Known Agents
@ -110,9 +104,7 @@ export default function Wrac() {
<TableBody> <TableBody>
{userAgents.map((agent) => ( {userAgents.map((agent) => (
<TableRow key={agent.client}> <TableRow key={agent.client}>
<TableCell className={"font-semibold"}> <TableCell className={"font-semibold"}>{agent.client}</TableCell>
{agent.client}
</TableCell>
<TableCell> <TableCell>
<code>{agent.regex}</code> <code>{agent.regex}</code>
</TableCell> </TableCell>
@ -121,8 +113,6 @@ export default function Wrac() {
))} ))}
</TableBody> </TableBody>
</Table> </Table>
<Footer />
</main> </main>
</div>
); );
} }

View File

@ -1,6 +1,4 @@
import NavBar from "@/components/NavBar"; import { ArrowLeft } from "lucide-react";
import Footer from "@/components/Footer";
import { ArrowLeft } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import Text from "@/components/blocks/Text"; import Text from "@/components/blocks/Text";
import PageTitle from "@/components/blocks/PageTitle"; import PageTitle from "@/components/blocks/PageTitle";
@ -9,11 +7,7 @@ import InlineCode from "@/components/blocks/InlineCode";
export default function Wrac() { export default function Wrac() {
return ( return (
<div className={"bg-stone-900 min-h-screen font-geist"}> <main className={"flex flex-col gap-4 w-full"}>
<main
className={"max-w-[700px] pt-15 flex flex-col gap-4 mx-auto w-full p-4"}
>
<NavBar />
<Link <Link
href={"/protocol"} href={"/protocol"}
className={ className={
@ -26,12 +20,11 @@ export default function Wrac() {
WebSocket Real Address Chat Protocol WebSocket Real Address Chat Protocol
</PageTitle> </PageTitle>
<Text> <Text>
WRAC (WebSocket Real Address Chat) is a community-made successor to WRAC (WebSocket Real Address Chat) is a community-made successor to RAC
RAC that uses WebSockets instead of TCP. It uses the same requests as that uses WebSockets instead of TCP. It uses the same requests as RAC,
RAC, but you should send data in binary format. Unlike regular RAC, but you should send data in binary format. Unlike regular RAC, you can
you can use the same connection multiple timesin RAC, you had to use the same connection multiple timesin RAC, you had to reconnect to
reconnect to the server for every request. This changes how message the server for every request. This changes how message receiving works.
receiving works.
</Text> </Text>
<Title id={"receiving-messages"}>Receiving messages</Title> <Title id={"receiving-messages"}>Receiving messages</Title>
<Text> <Text>
@ -40,14 +33,11 @@ export default function Wrac() {
</Text> </Text>
<Text> <Text>
Receiving messages in WRAC is done by sending a single packet to the Receiving messages in WRAC is done by sending a single packet to the
server with two bytes. The first byte is <InlineCode>0x00</InlineCode> server with two bytes. The first byte is <InlineCode>0x00</InlineCode>,
, which indicates that you want to receive messages, and the second which indicates that you want to receive messages, and the second byte
byte is either <InlineCode>0x01</InlineCode> or{" "} is either <InlineCode>0x01</InlineCode> or <InlineCode>0x02</InlineCode>
<InlineCode>0x02</InlineCode>. These two bytes work the same way as in . These two bytes work the same way as in RAC.
RAC.
</Text> </Text>
<Footer />
</main> </main>
</div>
); );
} }