Skip to content
Modern GUI for imageboards (4chan.org, 8ch.net, 2ch.hk, kohlchan.net)
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
assets/images
chan kohlchan icon fix Mar 20, 2019
configuration
docs Country flags added Mar 17, 2019
src Added author id colors Mar 20, 2019
webpack Refactored for kohlchan.net Mar 15, 2019
.gitignore
README.md
TODO.md Added voting markup Mar 20, 2019
babel.config.js
bfg.sh
package-lock.json
package.json
postcss.config.js
project.sublime-project

README.md

Modern GUI for imageboards (4chan.org, 8ch.net, 2ch.hk, kohlchan.net, etc).

4chan.org demo

8ch.net demo

2ch.hk demo

kohlchan.net demo

Don't mind the slower speeds: the app can't use chan APIs directly (they don't allow it) and needs to send all HTTP requests through a free public "CORS Proxy" which introduces a delay. Also, until "infinite scroll" (streaming) for loading threads and posts is implemented rendering the whole page takes a lot of time because there's a lot of comments to render. It will be fast once "infinite scroll" (streaming) feature is implemented.

This is a demo showcase project and currently has only a small subset of features. "To do":

  • Add "infinite scroll" (streaming) for loading threads and posts.
  • Add message posting.
  • Add thread watching.
  • Add thread auto-update.
  • Add "favorite" boards list.
  • Add dark mode.
  • Add a non-default theme.
  • Add support for "passes" (4chan.org, 2ch.hk).

Screenshots

Browsing

View in full resolution

Media

View in full resolution

Install

git clone git@github.com:catamphetamine/webapp-frontend.git
git clone git@github.com:catamphetamine/chanchan.git
cd chanchan
npm install

Develop

cd chanchan
npm run dev

Go to http://localhost:1234

Deploy

cd chanchan
npm run build

See the build/assets directory.

Proxy

All chans (4chan.org, 2ch.hk, etc) don't allow calling their API from other websites by prohibiting Cross-Origin Resource Sharing (CORS), so a CORS proxy is required in order for another website to be able to query chan API directly.

A public CORS proxy called "CORS Anywhere" can be used for development/testing. Such public CORS proxy imposes several restrictions such as no support for "cookies" and also introduces an artifical delay (a couple of seconds) for all API requests. There's also some list of public CORS proxies.

For production deployment a dedicated CORS proxy should be used. A free AWS EC2 "micro" server could be set up but CloudFlare blocks traffic from AWS EC2 (I guess because it can be easily set up for a DDoS attack) so 4chan.org, for example, won't work and will return 403 Forbidden for an AWS EC2 proxy.

An example of setting up a free AWS EC2 CORS proxy

AWS offers a year-long "free tier" usage plan for EC2 "micro" server instances.

  • Create a free EC2 "micro" instance.
  • Connect to it via SSH as ec2-user.
  • Install nginx: sudo amazon-linux-extras install nginx1.12
  • Auto start nginx: sudo chkconfig nginx on
  • Configure nginx: sudo nano /etc/nginx/nginx.conf
http {
	# This is required to resolve DNS names when proxying.
	resolver 172.31.0.2;

	# ... some standard configuration ...

	server {
		listen 80;
		server_name _; # applies for any domain name.

		# This setting is required to keep double slashes in the requested URL.
		merge_slashes off;

		# Only proxy URLs starting with "http://" or "https://".
		location ~* ^/https?://.+$ {
			# Serve `OPTIONS` "preflight" requests.
			if ($request_method = 'OPTIONS') {
				# Allow all websites access to this CORS proxy.
				# Could be restricted via an nginx variable.
				add_header Access-Control-Allow-Origin $http_origin;
				# Allow sending cookies as part of an HTTP request (optional).
				add_header Access-Control-Allow-Credentials true;
				# Allow all HTTP request headers.
				add_header Access-Control-Allow-Headers $http_access_control_request_headers;
				# Allow all HTTP request methods.
				add_header Access-Control-Allow-Methods $http_access_control_request_method;

				add_header Content-Type 'text/plain charset=UTF-8';
				add_header Content-Length 0;
				return 204;
			}

			# Allow all websites access to this CORS proxy.
			# " always" in the end is required for also setting
			# the CORS headers on "404 Not Found" responses.
			# Could be restricted via an nginx variable.
			add_header Access-Control-Allow-Origin $http_origin always;
			# Allow sending cookies as part of an HTTP request (optional).
			add_header Access-Control-Allow-Credentials true always;
			# Allow all HTTP request headers.
			add_header Access-Control-Allow-Headers $http_access_control_request_headers always;
			# Allow all HTTP request methods.
			add_header Access-Control-Allow-Methods $http_access_control_request_method always;

			# Trim the leading slash from `$request_uri` (URL path).
			rewrite ^/(.+)$ $1 break;

			# Generic proxying headers which are added to the proxied HTTP request.
			# This is just some info for the destination server that it may potentially use.
			# They are not required.
			#
			# Set the proxied HTTP request "HOST" header to this server's "HOST" (host and port).
			proxy_set_header HOST $host;
			# Which protocol did the client request.
			proxy_set_header X-Forwarded-Proto $scheme;
			# Pass client's IP address.
			proxy_set_header X-Real-IP $remote_addr;
			# The list of proxies used to proxy this HTTP request.
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			# Pass "If-Modified-Since" header to the server.
			proxy_set_header If-Modified-Since $http_if_modified_since;

			# (optional) Use HTTP/1.1 instead of the default HTTP/1.0.
			# For example, HTTP/1.1 has support for "entity tags" caching.
			proxy_http_version 1.1;

			# Proxy the HTTP request to the destination server.
			proxy_pass $1;
		}
	}
}
  • Reload nginx config: sudo service nginx reload

  • nginx should be working (HTTP should output a dummy webpage).

  • Next, an SSL certificate will be generated. "letsEncrypt" rejects AWS domains, so set up a free domain somehwere on dot.tk which will have a DNS A record pointing to the AWS server IP address.

  • Install certbot for issuing free "letsEncrypt" certificates:

# download, install, and Enable EPEL
wget -r --no-parent -A 'epel-release-*.rpm' http://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
sudo yum-config-manager --enable epel*
sudo yum repolist all

# install certbot
sudo yum install certbot
  • Create config for certbot: sudo mkdir -p /etc/letsencrypt && sudo nano /etc/letsencrypt/cli.ini
authenticator = webroot
webroot-path = /var/www/html
post-hook = systemctl reload nginx
text = True
  • Create a dummy "ACME challenge" response file: sudo mkdir -p /var/www/html/.well-known/acme-challenge && sudo sh -c "echo Success > /var/www/html/.well-known/acme-challenge/example.html"

  • Register in letsEncrypt network: sudo certbot register --email me@example.com

  • Configure nginx to serve "ACME challenge" response files:

server {
  ...
  location /.well-known {
    root /var/www/html;
  }
  ...
}
  • Check the dummy "ACME challenge" response: sudo service nginx reload && curl -L http://YOUR-DOMAIN-NAME-HERE/.well-known/acme-challenge/example.html

  • If it says "Success" then remove the dummy "ACME challenge" response file (certbot will create its own): sudo rm /var/www/html/.well-known/acme-challenge/example.html

  • Check certbot certificate issueance: sudo certbot certonly --dry-run -d YOUR_DOMAIN_NAME_HERE

  • If it says "The dry run was successful" then issue the certificate: sudo certbot certonly -d YOUR_DOMAIN_NAME_HERE

  • Set up nginx to use the generated certificates in the server entry:

server {
	listen 80;
	listen 443 ssl;
	...

	ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN_NAME_HERE/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN_NAME_HERE/privkey.pem;
	ssl_trusted_certificate /etc/letsencrypt/live/YOUR_DOMAIN_NAME_HERE/chain.pem;

	# Optimize certificate chain loading in a single round trip.
	ssl_stapling on;
	ssl_stapling_verify on;
	...
}
  • letsEncrypt certificates expire in 90 days, so schedule a daily renewal job:

sudo nano /etc/crontab:

# The job is run daily because certificates don't get
# renewed unless they are near to expiration.
0 8 * * * root certbot renew --quiet --allow-subset-of-names
  • Reload nginx config: sudo service nginx reload

  • HTTPS should be working.

In ./configuration/default.json there's corsProxyUrl setting — this is the CORS-proxy that will be used for querying chan API.

Chan API

4chan.org

2ch.hk

You can’t perform that action at this time.