4-ch over Gopher

  _ _               _    
 | | |   ___   __  | |_  
 |_  _| |___| / _| | ' \ 
   |_|        \__| |_||_|
                         

                        
  ___  __ __  ___   _ _ 
 / _ \ \ V / / -_) | '_|
 \___/  \_/  \___| |_|  
                        

   ___                _                
  / __|  ___   _ __  | |_    ___   _ _ 
 | (_ | / _ \ | '_ \ | ' \  / -_) | '_|
  \___| \___/ | .__/ |_||_| \___| |_|  
              |_|                      

╔─*──*──*──*──*──*──*──*──*──*──*──*──*──*──*──*──*──*──*╗
║1   ................................................   1║
║2*  ................................................  *2║
║3   ................................................   3║
║1   ...............Posted: 2026-01-25...............   1║
║2*  Tags: gopher haskell smallnet my_warez my_servs   *2║
║3   ................................................   3║
║1   ................................................   1║
╚────────────────────────────────────────────────────────╝

I wrote a tiny open source **4-ch.net viewer** that runs over **Gopher**.

The interesting part is the format.

It uses my *gopher applet* style: a **README that is also a literate Haskell
script**. You run it directly:

```
./4_ch.md
```

No build system. No framework. Just `runghc`.

Writing it this way felt like a strange inversion of TDD. Instead of tests, the
README comes first. The code exists to obey the explanation.

"README-driven design."

This works especially well for:

- small scripts
- teaching Haskell
- self-documenting infrastructure

It breaks down for large systems. That is a feature.

The applet plugs straight into **Venusia**, speaks RFC 1436 natively, and keeps
dependencies close to zero.

A 2000s textboard, viewed like its the 90s, implemented like a literate essay.

Live here: gopher://gopher.someodd.zip:70/1/gateway/4_ch

Source: https://github.com/someodd/small-gopher-applets/blob/master/4_ch.md