annotate mrjunejune/src/blog/my-seobeo-journey/index.md @ 149:f41ac17926d2

[Config] Added ctags scripts and actual tags.
author June Park <parkjune1995@gmail.com>
date Sat, 10 Jan 2026 07:07:10 -0800
parents 1c446ab6f945
children 295ac2e5ec00
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
109
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
1 # Creating Network Library in C
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
2
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
3 I’m so tired of modern web development. You want to spin up a simple web server, and suddenly you’re wrestling with a mountain of dependencies. Express, Fastify, whatever the flavor of the week is. They all promise simplicity, but dump a black hole of `node_modules` onto your machine. Have you ever actually looked inside? It’s insane. And all of them use React, Svelte, or whatever the current trend is for modern development. One time, I created a single React file using Bun and it had over 18k lines of JavaScript code lmao. And for what? To handle a simple HTTP request for a text file?
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
4
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
5 <img src="/public/23k.png" />
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
6
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
7 ** It was actually 23K lines long lol.. you can test it [here](https://zenbu.babocoder.com/file/tip/playground). Just clone the repo and run `bazel build playground:hello` **
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
8
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
9
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
10 ## So, I decided to build my own network library from scratch, in C.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
11
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
12 I call it `seobeo` because that is how Korean people say "server" with an accent. The goal is simple: create something fast, lightweight, and completely transparent. No magic, no hidden layers. Just a pure, unadulterated networking layer, with a web server interface built on top of it.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
13
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
14 ## Where to begin?
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
15
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
16 I’d never really dealt with network libraries, nor had I written much C outside of a few contract jobs, so starting was a learning curve. I did a quick Google search and found an [amazing guide to network programming](https://beej.us/guide/bgnet/html/split/). In it, Beej talks about networking from scratch and explains many socket library functions in detail. He provides examples and explains the "why" behind the setup, so I highly recommend people check that out first.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
17
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
18 After that, I looked at a few examples from [Eskil Steenberg’s](https://www.google.com/search?q=https://www.quelsolaar.com/about/index.html) [GitHub repo](https://github.com/valiet/quel_solaar/tree/main/Testify), which was super useful for seeing how he approached API design.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
19
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
20 ## The Core Concept
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
21
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
22 The whole library is built around a central `Seobeo_Handle` struct. This struct handles all server-related information, holding everything from the socket file descriptor to the read/write buffers, as well as SSL-related data. This allows API callers to decide how they want to serialize the bytes and write/read from them.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
23
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
24 ```c
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
25 typedef struct {
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
26 int32 socket;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
27 Seobeo_SocketType type;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
28 boolean connected;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
29
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
30 char *host;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
31 char *port;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
32
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
33 uint8 *read_buffer;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
34 uint32 read_buffer_capacity;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
35 uint32 read_buffer_len;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
36 uint32 read_buffer_used;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
37
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
38 SSL_CTX_TYPE *ssl_ctx;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
39 SSL_TYPE *ssl;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
40
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
41 uint8 *write_buffer;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
42 uint32 write_buffer_capacity;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
43 uint32 write_buffer_len;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
44
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
45 void *file;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
46 void *text_copy;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
47 char *file_name;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
48
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
49 atomic_bool destroyed;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
50 } Seobeo_Handle;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
51
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
52 ```
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
53
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
54 ## Creating the Web Server Library
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
55
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
56 From here, it was incredibly simple to create the web client and server logic, since all I had to do was send a string of bytes to request information. It was refreshing to be able to set exact header values without going through a library; receiving information byte-by-byte was actually fun.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
57
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
58 ```c
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
59 // Manually craft the raw HTTP request string
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
60 char request[4096];
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
61 int request_len = sprintf(
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
62 request,
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
63 "GET / HTTP/1.1\r\n"
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
64 "Host: example.com\r\n"
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
65 "Connection: close\r\n"
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
66 "\r\n"
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
67 );
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
68
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
69 // Queue the raw text...
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
70 Seobeo_Handle_Queue(h, (uint8*)request, (uint32)request_len);
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
71 // ...and flush it to the socket.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
72 int flush_result = Seobeo_Handle_Flush(h);
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
73
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
74 ```
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
75
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
76 **While the logic is simple, I made plenty of mistakes along the way. I eventually had to create my own utility library (using Arenas, dynamic arrays, and hashmaps) just to make implementing the basic logic easier to manage.**
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
77
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
78 Things only got complicated when I had to deal with SSL, as I wanted to be able to make encrypted calls, but I just had to hunker down and learn how SSL worked.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
79
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
80 On the server side, I kept the API dead simple: the server is granted access to a folder, and you can add your own router logic before initializing the server. As you can see below, your custom routing is always checked first, followed by static paths. I had to write a lot of code to handle different data types, but the logic remained straightforward. If you want to add a custom header, you just add it to the response hashmap.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
81
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
82 ```c
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
83 #include "seobeo/seobeo.h"
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
84
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
85 // Handler for GET /api/v1/hello
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
86 Seobeo_Request_Entry* GetHello(Seobeo_Request_Entry *req, Dowa_Arena *arena) {
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
87 Seobeo_Request_Entry *resp = NULL;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
88 const char *body = "{\"message\": \"Hello from Seobeo!\"}";
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
89
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
90 // Build the response map
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
91 Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
92 Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
93 Dowa_HashMap_Push_Arena(resp, "body", body, arena);
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
94
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
95 return resp;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
96 }
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
97
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
98 int main() {
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
99 Seobeo_Router_Init();
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
100 // Register the route
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
101 Seobeo_Router_Register("GET", "/api/v1/hello", GetHello);
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
102 // Start the server
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
103 Seobeo_Web_Server_Start("./public", "8080", SEOBEO_MODE_EDGE, 4);
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
104 return 0;
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
105 }
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
106
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
107 ```
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
108
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
109 No dependency injection, no middleware chains, no magic. Just a function that takes a request and returns a response. I updated the API so it can run as a multi-threaded, asynchronous process using system-level libraries like `epoll` or `kqueue`. I tested it with `Locust` at over 2,000 requests per second (my internet’s limit, lol) without Cloudflare, and it worked perfectly.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
110
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
111 ## The Payoff and Trade-offs
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
112
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
113 But here’s the best part: the final executable for my entire website, running on `seobeo`, is just **81 kB** (excluding static assets) and uses only **1.1 MB** of memory before server-side caching.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
114
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
115 That’s smaller than the `package.json` file of most modern web projects. It’s a rounding error in the world of Express or Python web frameworks. I understand that it doesn't have every feature, and people might worry about security (though I’m not too concerned since the server runs as a limited user with just static files), but it’s still a massive victory in my book.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
116
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
117 I know what you’re thinking. "But you have to write so much code" or "This code sucks" or whatever. And you're probably right. I have to manually craft HTTP headers. I have to manage my own memory with arena allocators. I even wrote my own integration test framework just to verify the HTTP client.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
118
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
119 But I’ll take that trade-off any day of the week.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
120
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
121 Why? Because I actually know what’s going on. The whole stack is right there in front of me. Plus, in the age of cloud infrastructure, most of the complex stuff is handled upstream anyway. My typical setup is **Cloudflare -> Nginx -> my server**. Cloudflare handles HTTPS; Nginx handles proxying and load balancing. Why should my application server bother with SSL handshakes when it’s sitting deep inside a trusted network? It’s redundant and just adds another layer of complexity.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
122
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
123 FYI, I am running this website on seobeo library and everything you see in this website from start to finish is written by me from now on.
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
124
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
125 ## TODOs?
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
126
1c446ab6f945 [MrJuneJune] New Blog about writing Seobeo library.
June Park <parkjune1995@gmail.com>
parents:
diff changeset
127 I’m planning to build out a WebSocket layer and an MCP (Message Control Protocol) implementation for some other crazy projects I have in mind, just to see how complicated they are to write because I like writing code. [Link to Library](https://zenbu.babocoder.com/file/tip/seobeo);