catamphetamine / anychan

A universal web client for online discussion services like "forums" or "imageboards".
https://anychans.github.io
75 stars 7 forks source link

anychan

A universal web client for online discussion services like "forums" or "imageboards".

Supported data sources:

Don't mind the seemingly slower speed of the demos: the only reason for that is the app can't use imageboard APIs directly (they don't allow it) and needs to send all HTTP requests through a free public "CORS Proxy" which introduces a delay.

GitHub

On March 9th, 2020, GitHub, Inc. silently banned my account (erasing all my repos, issues and comments) without any notice or explanation. Because of that, all source codes had to be promptly moved to GitLab. The GitHub repo is now only used as a backup (you can star the repo there too), and the primary repo is now the GitLab one. Issues can be reported in any repo.

Hosting

The application is distributed in the form of "releases" ("builds"). The "builds" can be found on GitLab Releases page, but those're most likely stale, so I'd recommend creating your own "build" from the sources as described in the Build section.

A "build" contains an index.html file and a bunch of .js/.css/.map/image files with random generated names (and also about a 100 of code syntax highlighter language plugins that are only loaded on demand at runtime when highlighting a given language in "code" blocks).

Inside a "build", find and edit the index.html file in order to specify custom configuration options such as:

Those custom configuration options should be specified at the top of the index.html file in the global CONFIG variable:

<html>
  <head>
    <script>
      // Set your config parameters here.
      // https://gitlab.com/catamphetamine/anychan#configuration
      var CONFIG = {
        "path": "/my-custom-file-hosting-path",
        "dataSource": "my-custom-default-data-source-id",
        "youtubeApiKey": "my-custom-youtube-api-key",
        "googleAnalyticsId": "my-custom-google-analytics-id"
      }
    </script>
...

After saving the changes to the index.html file, the contents of the "build" folder should be "statically" hosted somewhere, be it on a server using "static" file hosting software (like NginX), or somewhere in a "cloud" (like Amazon S3 + CloudFront).

When hosting the contents of a "build", make sure that all "404 Not Found" requests are redirected to that index.html file. For example, on AWS S3, that could be done by specifying index.html as the name of the "error document". Another example would be GitHub Pages where index.html file should be copied into a new file called 404.html.

To create a most-recent "build" from the latest source codes, one should perform a manual build process documented in the Build section.

Configuration

The application provides several configuration options like YouTube API key, Google Analytics id, etc.

The default configuration can be found in ./configuration/default.json file. Any custom configuration is applied on top of it. Custom configuration can be specified at the top of the index.html file in the global CONFIG variable.

See types/Configuration.ts for the most up-to-date description of a configuration object.

Configuration options ##### ```js { // The `dataSource` parameter describes the data source being used. // // If the data source is a "supported-out-of-the-box" one, // then the "dataSource" parameter can be set to such data source name: // // * "4chan" // * "8ch" // * "2ch" // * "kohlchan" // * "lainchan" // * etc // // Specifying the "dataSource" parameter in such cases can be omitted // if this application runs on the data source's main domain (e.g. "4chan.org") // because the application is smart enough to detect that type of situation // and will automatically determine the correct data source name. // In other cases — when running the application on other domains — // specifying a data source is required, unless you'd prefer the application // to run in a "multi-datasource" mode in which case it will require // a data source name as a URL path prefix. For example, "https://domain.com/4chan/b". // // When a data source is not a "supported-out-of-the-box" one, // the "dataSource" configuration parameter value should be an object // describing various parameters of the data source: // // * `logo` // * `title` // * `api` // * etc // // See "Data Sources" section of the docs for more info on // the available configuration parameters for a custom data source. // "dataSource": "4chan", // Data source icon. // Overwrites `dataSource.icon`. // Should be of `192px` width and `192px` height. "icon": "https://s.4cdn.org/image/favicon.ico", // Data source logo (a larger version of an icon). // Overwrites `dataSource.logo`. "logo": "https://s.4cdn.org/image/fp/logo-transparent.png", // Data source title. // Overwrites `dataSource.title`. "title": "4chan", // Data source "subtitle" (the text under the title on the home page). // Overwrites `dataSource.subtitle`. "subtitle": "Since 2003", // Home page content. // Overwrites `dataSource.description`. // https://gitlab.com/catamphetamine/social-components/blob/master/docs/Post/PostContent.md "description": [ { type: "attachment", // An attachment could be a picture, a video (including YouTube), an audio, etc. // https://gitlab.com/catamphetamine/social-components/blob/master/docs/Post/PostContentTypes.md attachment: { type: "picture", picture: { type: "image/jpeg", width: 600, height: 438, url: "https://s.4cdn.org/image/news/Happybirthday_17th_th.jpg" } } }, "4chan is a simple image-based bulletin board where anyone can post comments and share images" ], // Any arbitrary javascript that will be inserted on every page. // Can be used to modify the page in an arbitrary way: // * Insert new ` ```
Themes ##### To add custom themes to the list of built-in themes, supply `themes` configuration parameter: ```js { ... themes: [ { // An "ID" (for reference). id: "yellow-sea", // A human-readable name. name: "Yellow Sea", // Either a URL of a `*.css` file: url: "https://yellow.sea/style.css", // or CSS itself: css: ".light { --Clickable-color: yellow } .dark { --Clickable-color: blue }" }, ... ] } ``` To set a theme as the default one, set `defaultTheme` configuration parameter to the `id` of the theme: ```js { ... defaultTheme: "yellow-sea" } ``` To translate a theme's name in different languages, add the entries in `LABELS`: ```html ```

Themes

The app comes pre-packaged with a couple of built-in themes and allows creating custom themes. Each theme has "Light" mode and "Dark" mode.

Proxy

None of the imageboards (4chan.org, 8kun.top, 2ch.hk, etc) allow calling their API from other websites: they're all configured to block Cross-Origin Resource Sharing (CORS), so a CORS proxy is required in order for a third party website to be able to query their API.

Read more

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

Known issues

Server-Side Rendering

This application uses React, and can be rendered both on client side and server side. But, React is rumoured to be rather slow when it comes to server-side rendering, compared to the "classic" way of generating web pages from simple templates (like PHP). I didn't benchmark server-side rendering of this app, but I'd assume that, for a high-load website, it would make a difference to use a more performant solution (cost-wise). Maybe it could be some kind of a separate "static" "archive" version that would be very minimalistic, and would be easily indexed by search engines. Both Google and Bing still can index client-side websites that use javascript for the initial loading, but a separate "static" website would most likely get better "score".

More details ##### This application is built using [`react-pages`](https://www.npmjs.com/package/react-pages) library which does support server-side rendering. Why even implement server-side rendering? One reason would be for the website to be indexable by search engines in order to be discoverable on the internet. However, I wouldn't consider server-side rendering suitable for this specific application: * When I originally started this project in August 2018, React used to be not so performant when it comes to server-side rendering. Writing this section now in October 2023, I didn't bother checking if that situation has changed. So I'll just assume that React, although reasonably fast, it still not the most performant solution when it comes to outputting raw HTML when compared to more simplistic template-based rendering engines that don't even bother executing any javascript. So, for example, an imageboard could employ dual-website strategy: one website could be statically generated and would drive the traffic to the website from search engines, and another website would be this interactive React "Single-Page Application" that doesn't bother with server-side rendering and provides User Experience. * This application uses [`virtual-scroller`](https://www.npmjs.com/package/virtual-scroller) to only render the currently-visible portion of large lists of comments or threads when run in a web browser. On server side, it would have to render the full lists of those comments. Suppose that's not an issue by itself to the server. But after rendering those large lists of comments on the server, they'd have to be [re-"hydrated"](https://www.gatsbyjs.com/docs/conceptual/react-hydration/) on the client in order to make al that raw HTML snapshot interactive and running. And while doing re-"hydration" on the client, it would have to render the page 1:1 of how it was rendered on the server, meaning that on the client it would have to also render those large lists of comments. And I've tested how rendering large lists of comments performed at the initial stages of developing this application in 2019, and the performance wasn't acceptable: somewhere in the magnitude of 1 second for a list of about a 1000 comments, which is nowhere near being considered "swift".

Virtualized Lists

The lists of threads/comments are implemented via a "Virtual Scroller" which results in great performance boost but at the same time doesn't support some native in-browser features such as "Find on page" or "Tab" key navigation or "screen readers".

Imageboards

For known imageboard issues, see known issues of the imageboard library.

Development

First, install Node.js >= 16.

Then perform the initial setup:

# Install "frontend-lib"
git clone https://gitlab.com/catamphetamine/frontend-lib.git
cd frontend-lib
yarn link
cd ..

# Install "social-components-react"
git clone https://gitlab.com/catamphetamine/social-components-react.git
cd social-components-react
yarn link
cd ..

# Install "anychan"
git clone https://gitlab.com/catamphetamine/anychan.git
cd anychan
yarn
yarn link frontend-lib
yarn link social-components-react

After the initial setup has been completed, the application could be run via:

yarn run dev

Because this project uses TypeScript, the initial start-up time is quite long.

Wait for it to load and go to http://localhost:1234

To specify custom configuration options (like YouTube API key), one could create a file called configuration/custom.json. The contents of that file would be applied on top of the default configuration when running via yarn run dev or yarn run build.

Also, check if the proxy server that is configured by default still works. If it doesn't, the application will show an error page. In that case:

In future, in case of "pulling" any changes, don't forget to re-run the yarn command to update the packages.

Build

To create a build from the sources, follow the instructions in the Development section above, but, at the last step, instead of running yarn run dev, run yarn run build.

The contents of the "build" will be output to the build directory:

To create a *.zip archive of a build, run yarn run build:pack command.

Test

There're some tests written for "utility" functions.

yarn test

Data Sources

anychan supports any data source. It could be an online forum, an imageboard, something like reddit.com, etc. For example, imageboards are supported "out of the box".

To add a new data source, follow the instructions in docs/add-new-data-source.md.

Miscellaneous

License

MIT