├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── add.md │ └── report.md └── workflows │ └── live.yml ├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── package-lock.json ├── package.json └── src ├── CNAME ├── checks.js ├── favicon.png ├── metrics.js ├── refresh.js ├── render.js ├── template.html └── urls.yaml /.gitattributes: -------------------------------------------------------------------------------- 1 | /package-lock.json linguist-generated 2 | /src/template.html -linguist-detectable 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/add.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Suggest new website 3 | about: Suggest a new website or web application to be added to the 10 KB Club 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **What is the URL of the website or web application you want to add?** 10 | 11 | (Replace this line with your answer.) 12 | 13 | **What is the total size of data transferred while loading your URL in a web browser? (See [club rules](https://10kbclub.com/#club-rules) > point 1 to figure how to measure the data transfer size.)** 14 | 15 | (Replace this line with your answer.) 16 | 17 | **Provide one or more links to discussions on Reddit or Hacker News where some content from your website received at least 100 upvotes.** 18 | 19 | (Replace this line with one or more links.) 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report an issue 3 | about: Report an issue with the 10 KB Club 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /.github/workflows/live.yml: -------------------------------------------------------------------------------- 1 | name: Rebuild website and make it live 2 | 3 | on: 4 | push: 5 | schedule: 6 | - cron: 9 1 * * 6 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - run: date; pwd; ls -l 14 | - run: make build-setup 15 | - run: make render 16 | - run: make live 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw? 2 | node_modules/ 3 | node/ 4 | node.txz 5 | env 6 | metrics.yaml 7 | index.html 8 | favicon.png 9 | CNAME 10 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright (c) 2020 Susam Pal 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | render: 2 | . ./env && npm run lint 3 | . ./env && node src/checks.js 4 | . ./env && node src/refresh.js 5 | . ./env && node src/render.js 6 | cp src/favicon.png . 7 | cp src/CNAME . 8 | 9 | checks: 10 | node src/checks.js 11 | 12 | mac-setup: 13 | brew install node 14 | > env 15 | npm install 16 | 17 | deb-setup: 18 | curl -sSL https://nodejs.org/dist/v18.12.1/node-v18.12.1-linux-x64.tar.xz -o node.txz 19 | mkdir -p node/ 20 | tar -xvf node.txz -C node --strip-components=1 21 | echo "PATH=$$PWD/node/bin:\$$PATH" > env 22 | sudo apt-get install chromium 23 | . ./env && npm install 24 | 25 | build-setup: 26 | sudo apt-get install nodejs 27 | > env 28 | npm install 29 | 30 | live: 31 | git config user.name "make" 32 | git config user.email "make@localhost" 33 | git branch -D live; : 34 | git switch -f --orphan live 35 | git add index.html favicon.png CNAME 36 | git commit -m "Publish live ($$(date -u +"%Y-%m-%d %H:%M:%S"))" 37 | git log -n 5 38 | git push -f origin live 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 10 KB Club 2 | ========== 3 | 4 | **NOTE: This project is no longer maintained.** 5 | 6 | This is the source code of [10kbclub.com][website]. 7 | 8 | [website]: https://10kbclub.com/ 9 | 10 | 11 | Contents 12 | -------- 13 | 14 | * [Suggest New Website](#suggest-new-website) 15 | * [Development Setup](#development-setup) 16 | * [Commit Guidelines](#commit-guidelines) 17 | * [Additional Details](#additional-details) 18 | * [License](#license) 19 | * [Support](#support) 20 | 21 | 22 | Suggest New Website 23 | ------------------- 24 | 25 | Read the [Club Rules][rules] first. If the new website satisfies the 26 | club rules, then [create a new issue][new issue] and provide the URL of 27 | the website. 28 | 29 | [rules]: https://10kbclub.com/#club-rules 30 | [new issue]: https://github.com/susam/10kbclub/issues/new?template=add.md 31 | 32 | 33 | Development Setup 34 | ----------------- 35 | 36 | To build and develop this project locally, perform the following steps: 37 | 38 | 1. Clone this repository: 39 | 40 | ```sh 41 | git clone https://github.com/susam/10kbclub.git 42 | ``` 43 | 44 | 2. Install Node. 45 | 46 | On macOS, enter the following command if you have 47 | [Homebrew](https://brew.sh): 48 | 49 | ```sh 50 | make mac-setup 51 | ``` 52 | 53 | On Debian, Ubuntu, or another Debian-based Linux system, enter the 54 | following command: 55 | 56 | ``` 57 | make deb-setup 58 | ``` 59 | 60 | 3. Enter the following command to create a local copy of the website: 61 | 62 | ```sh 63 | make render 64 | ``` 65 | 66 | 4. Now open `index.html` using a web browser to see the output. 67 | 68 | 69 | Development Activities 70 | ---------------------- 71 | 72 | 1. On a Linux system, enter the following command to ensure that the 73 | directory for Node binaries are added to the `PATH` environment 74 | variable: 75 | 76 | ```sh 77 | . ./env 78 | ``` 79 | 80 | 2. Enter the following command to generate a file named 81 | `metrics.yaml` that would contain metrics data for each URL in the 82 | file `src/urls.yaml`: 83 | 84 | ```sh 85 | node src/refresh.js 86 | ``` 87 | 88 | 3. Enter the following command to render the home page using the data 89 | in `metrics.yaml`: 90 | 91 | ```sh 92 | node src/render.js 93 | ``` 94 | 95 | 4. Enter the following command to fetch a single URL and print its 96 | metrics: 97 | 98 | ```sh 99 | node src/metrics.js https://www.example.com/ 100 | ``` 101 | 102 | This script also accepts multiple URL arguments like this: 103 | 104 | ```sh 105 | node src/metrics.js https://www.example.com/ https://www.example.org/ 106 | ``` 107 | 108 | 109 | Commit Guidelines 110 | ----------------- 111 | 112 | The following guidelines are followed in the commits made manually: 113 | 114 | 1. The following commands should succeed without errors: 115 | 116 | ```sh 117 | make checks 118 | make render 119 | ``` 120 | 121 | 2. Commit messages are written as per the guidelines in this document: 122 | [Writing Good Commit Messages][commit-conventions]. 123 | 124 | [commit-conventions]: https://github.com/erlang/otp/wiki/Writing-good-commit-messages 125 | 126 | 127 | Additional Details 128 | ------------------ 129 | 130 | This section contains some additional details that might be useful in 131 | understanding this project. 132 | 133 | 1. The project repository at https://github.com/susam/10kbclub is 134 | automatically published as https://10kbclub.com/ using [GitHub 135 | Pages][gh-pages]. 136 | 137 | 2. The build job to publish the website runs automatically once every 138 | Saturday as well as on every push via GitHub Actions. See 139 | [`live.yml`] for the GitHub Actions workflow. See 140 | https://github.com/susam/10kbclub/actions for the previous 141 | executions of the workflow. 142 | 143 | 3. The links to discussion threads in [`js/urls.yaml`] are not 144 | exhaustive. Only the 5 earliest discussion threads that have 145 | 100 points or more have been picked from each forum. 146 | 147 | [`live.yml`]: .github/workflows/live.yml 148 | [`js/urls.yaml`]: js/urls.yaml 149 | [gh-pages]: https://pages.github.com/ 150 | [actions]: https://github.com/susam/10kbclub/actions 151 | 152 | 153 | License 154 | ------- 155 | 156 | This is free and open source software. You can use, copy, modify, 157 | merge, publish, distribute, sublicense, and/or sell copies of it, 158 | under the terms of the MIT License. See [LICENSE.md][L] for details. 159 | 160 | This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, 161 | express or implied. See [LICENSE.md][L] for details. 162 | 163 | [L]: LICENSE.md 164 | 165 | 166 | Support 167 | ------- 168 | 169 | To report bugs, suggest improvements, or ask questions, 170 | [create issues][ISSUES]. 171 | 172 | [ISSUES]: https://github.com/susam/10kbclub/issues 173 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10kbclub", 3 | "version": "0.1.0-dev", 4 | "description": "10 KB Club website generator", 5 | "homepage": "http://github.com/susam/10kbclub", 6 | "bugs": "http://github.com/susam/10kbclub/issues", 7 | "license": "MIT", 8 | "author": "Susam Pal (https://susam.in/)", 9 | "repository": "github:susam/10kbclub", 10 | "dependencies": { 11 | "phantomas": "^2.0.0", 12 | "yaml": "^2.0.0" 13 | }, 14 | "devDependencies": { 15 | "standard": "^16.0.0" 16 | }, 17 | "scripts": { 18 | "lint": "standard --verbose" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/CNAME: -------------------------------------------------------------------------------- 1 | 10kbclub.com 2 | -------------------------------------------------------------------------------- /src/checks.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const yaml = require('yaml') 4 | 5 | function forumPriority (forumURL) { 6 | if (forumURL.startsWith('https://www.reddit.com/')) { 7 | return 1 8 | } else if (forumURL.startsWith('https://news.ycombinator.com/')) { 9 | return 2 10 | } else if (forumURL.startsWith('https://lobste.rs/')) { 11 | return 2 12 | } else { 13 | return -1 14 | } 15 | } 16 | 17 | function main () { 18 | const urlPath = path.join(__dirname, 'urls.yaml') 19 | const urlData = yaml.parse(fs.readFileSync(urlPath, 'utf8')) 20 | 21 | let prevURL = '' 22 | for (const urlItem of urlData) { 23 | // Validate that URLs are in ascending order. 24 | const currURL = urlItem.url 25 | if (currURL < prevURL) { 26 | console.log('Website', currURL, 'must come earlier in the list') 27 | return 28 | } 29 | prevURL = currURL 30 | 31 | // Validate that discussion URLs are in (forum priority, date) order. 32 | let prevForumPriority = 0 33 | let prevDate = '' 34 | for (const d of urlItem.discussions) { 35 | // Validate that discussion URLs are in forum priority order. 36 | const currForumPriority = forumPriority(d.url) 37 | if (currForumPriority === -1) { 38 | console.log('Discussion', d.url, 'is from an unrecognized forum') 39 | return 40 | } else if (currForumPriority < prevForumPriority) { 41 | console.log('Discussion', d.url, 'must come earlier in the', 42 | 'list due to forum priority') 43 | return 44 | } else if (currForumPriority > prevForumPriority) { 45 | prevDate = '' 46 | } 47 | prevForumPriority = currForumPriority 48 | 49 | // Validate that discussion URLs are in chronological order. 50 | const currDate = d.date 51 | if (currDate < prevDate) { 52 | console.log('Discussion', d.url, 'must come earlier in the', 53 | 'list due to date order') 54 | return 55 | } 56 | prevDate = currDate 57 | } 58 | } 59 | } 60 | 61 | main() 62 | -------------------------------------------------------------------------------- /src/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spxy/10kbclub/2e47bf4d2e60897b9de4cdc549cc5cf9e75ea5b2/src/favicon.png -------------------------------------------------------------------------------- /src/metrics.js: -------------------------------------------------------------------------------- 1 | const phantomas = require('phantomas') 2 | 3 | async function fetchURL (url) { 4 | console.log('url:', url) 5 | const r = await phantomas(url) 6 | const m = r.getMetrics() 7 | 8 | console.log('base64Size:', m.base64Size, '(no transfer)') 9 | console.log('cssSize:', m.cssSize) 10 | console.log('htmlSize:', m.htmlSize) 11 | console.log('imageSize:', m.imageSize) 12 | console.log('jsSize:', m.jsSize) 13 | console.log('jsonSize:', m.jsonSize) 14 | console.log('otherSize:', m.otherSize) 15 | console.log('videoSize:', m.videoSize) 16 | console.log('webfontSize:', m.webfontSize) 17 | console.log('contentLength:', m.contentLength) 18 | 19 | const contentSize = m.htmlSize + m.jsonSize + m.imageSize + m.videoSize 20 | const extraSize = m.cssSize + m.jsSize + m.webfontSize + m.otherSize 21 | const totalSize = contentSize + extraSize 22 | const contentRatio = 100 * (contentSize / m.contentLength) 23 | 24 | console.log('contentSize:', contentSize, '(computed)') 25 | console.log('extraSize:', extraSize, '(computed)') 26 | console.log('totalSize:', totalSize, '(computed)') 27 | console.log('contentLength === totalSize:', m.contentLength === totalSize) 28 | console.log() 29 | 30 | return { 31 | url: url, 32 | contentSize: contentSize, 33 | totalSize: m.contentLength, 34 | contentRatio: contentRatio 35 | } 36 | } 37 | 38 | function textSummary (urlMetrics) { 39 | return [ 40 | (urlMetrics.totalSize / 1024).toFixed(1) + ' KB', 41 | (urlMetrics.contentSize / 1024).toFixed(1) + ' KB', 42 | urlMetrics.contentRatio.toFixed(0) + '%' 43 | ] 44 | } 45 | 46 | function htmlSummary (urlMetrics) { 47 | const [totalKB, contentKB, contentRatio] = textSummary(urlMetrics) 48 | return [ 49 | totalKB.replace(' ', ' '), 50 | contentKB.replace(' ', ' '), 51 | contentRatio.replace(' ', ' ') 52 | ] 53 | } 54 | 55 | async function main () { 56 | const args = process.argv.slice(2) 57 | for (const arg of args) { 58 | const urlMetrics = await fetchURL(arg) 59 | const [totalKB, contentKB, contentRatio] = textSummary(urlMetrics) 60 | console.log('total size:', totalKB) 61 | console.log('content size:', contentKB) 62 | console.log('content ratio:', contentRatio) 63 | console.log() 64 | } 65 | } 66 | 67 | if (require.main === module) { 68 | main() 69 | } 70 | 71 | module.exports = { 72 | fetchURL: fetchURL, 73 | textSummary: textSummary, 74 | htmlSummary: htmlSummary 75 | } 76 | -------------------------------------------------------------------------------- /src/refresh.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const yaml = require('yaml') 4 | const metrics = require('./metrics') 5 | 6 | async function refreshMetrics (urlList) { 7 | const metricsList = [] 8 | for (const [index, url] of urlList.entries()) { 9 | console.log('Fetching URL', (index + 1), 'of', urlList.length) 10 | let urlMetrics 11 | try { 12 | urlMetrics = await metrics.fetchURL(url) 13 | } catch (e) { 14 | console.log('Error while fetching:', e) 15 | console.log('Ignoring', url, 'due to error\n') 16 | continue 17 | } 18 | if (urlMetrics.totalSize > 10240) { 19 | console.log('Ignoring', url, 'because totalSize is too large\n') 20 | continue 21 | } 22 | metricsList.push(urlMetrics) 23 | } 24 | return metricsList.sort((a, b) => a.totalSize - b.totalSize) 25 | } 26 | 27 | function writeMetrics (metricsList) { 28 | const urlMetrics = { 29 | metricsTime: new Date().toUTCString(), 30 | metricsList: metricsList 31 | } 32 | const yamlString = yaml.stringify(urlMetrics, null, 2) + '\n' 33 | const metricsPath = path.join(__dirname, '..', 'metrics.yaml') 34 | fs.writeFileSync(metricsPath, yamlString, 'utf8') 35 | console.log('Updated metrics.yaml with latest data') 36 | } 37 | 38 | async function main () { 39 | const urlPath = path.join(__dirname, 'urls.yaml') 40 | const urlData = yaml.parse(fs.readFileSync(urlPath, 'utf8')) 41 | const urlList = urlData.map(item => item.url) 42 | const metricsList = await refreshMetrics(urlList) 43 | writeMetrics(metricsList) 44 | } 45 | 46 | main() 47 | -------------------------------------------------------------------------------- /src/render.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const yaml = require('yaml') 4 | const metrics = require('./metrics') 5 | 6 | function makeDiscussionHTML (discussions) { 7 | let html = `

8 | See the following discussions on content from this website: 9 |

10 | ' 32 | return html 33 | } 34 | 35 | function makeRowHTML (rank, urlMetrics, discussions) { 36 | const url = urlMetrics.url 37 | const website = url.replace(/^https?:\/\//, '').replace(/\/$/, '') 38 | const totalSize = urlMetrics.totalSize 39 | const contentSize = urlMetrics.contentSize 40 | const [totalKB, contentKB, contentRatio] = metrics.htmlSummary(urlMetrics) 41 | const discussionHTML = makeDiscussionHTML(discussions) 42 | return ` 43 | ${rank}. 44 | ${website} 45 | ${totalKB} 46 | ${contentKB} 47 | ${contentRatio} 48 | 49 | 50 | 51 | ${discussionHTML} 52 | 53 | \n` 54 | } 55 | 56 | function main () { 57 | const urlMap = {} 58 | const urlPath = path.join(__dirname, 'urls.yaml') 59 | const urlData = yaml.parse(fs.readFileSync(urlPath, 'utf8')) 60 | for (const urlItem of urlData) { 61 | urlMap[urlItem.url] = urlItem 62 | } 63 | 64 | const metricsPath = path.join(__dirname, '..', 'metrics.yaml') 65 | const urlMetrics = yaml.parse(fs.readFileSync(metricsPath, 'utf8')) 66 | 67 | let rowsHTML = '' 68 | for (const [i, m] of urlMetrics.metricsList.entries()) { 69 | rowsHTML += makeRowHTML(i + 1, m, urlMap[m.url].discussions) 70 | } 71 | console.log('rowsHTML:\n', rowsHTML) 72 | 73 | const metricsTime = urlMetrics.metricsTime 74 | const date = metricsTime.substring(0, 16) 75 | const time = metricsTime.substring(17, 22) + metricsTime.substring(25) 76 | console.log('date:', date) 77 | console.log('time:', time) 78 | 79 | const templatePath = path.join(__dirname, 'template.html') 80 | const template = fs.readFileSync(templatePath, 'utf8') 81 | const output = eval('`' + template + '`') // eslint-disable-line no-eval 82 | const outputPath = path.join(__dirname, '..', 'index.html') 83 | fs.writeFileSync(outputPath, output, 'utf8') 84 | console.log('Done rendering index.html') 85 | } 86 | 87 | main() 88 | -------------------------------------------------------------------------------- /src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 KB Club 5 | 6 | 7 | 8 | 9 | 46 | 67 | 68 | 69 | 70 |

10 KB Club

71 |

72 | The 10 KB Club is a curated collection of websites whose home pages 73 | do not exceed 10 KB compressed size. See this GitHub repository for 75 | the source code of this website. 76 |

77 |

78 | The Club Rules section specify the 79 | eligibility criteria for websites to be a member of this club. To 80 | suggest a new website to be added to this 81 | list, create 82 | a new issue on GitHub. 83 |

84 | 85 |

Club Members

86 |

87 | The following websites are members of the 10 KB Club. Click 88 | anywhere on a row (except on the website name) to see links to popular 89 | Reddit and Hacker News discussions on content belonging to the 90 | website. The oldest five popular discussions from each forum have been 91 | picked for this list. 92 |

93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | ${rowsHTML}
#WebsiteTotal SizeContent SizeContent Ratio
102 |

103 | The data in the table above was fetched on ${date} at ${time}. This 104 | data is refreshed automatically every Saturday as well as on every 105 | push to its GitHub 106 | repository. 107 |

108 |

109 | Do not take the content size and content ratio columns too seriously. 110 | The content size is calculated using refresh.js 112 | in the source code of the repository. It is not always accurate. For 113 | example, it considers internal CSS to be content but external CSS to be 114 | not content. Therefore, home pages that use CSS within an HTML page have 115 | an unfair advantage to get a higher content ratio than it should. 116 |

117 | 118 |

Club Rules

119 |

120 | Each website that is a member of the 10 KB Club is identified by a 121 | URL to its home page. The URL must satisfy the following rules: 122 |

123 |
    124 |
  1. 125 |

    126 | If the URL is opened in a web browser with no ad blockers or 127 | script blockers enabled, the compressed data that the web browser 128 | has to fetch to load the complete web page must not exceed 10240 129 | bytes. To check this on Firefox or Chrome, open a new 130 | private/incognito window, then right click on the blank page and 131 | select "Inspect", then go to the "Network" tab, and finally enter 132 | the URL in the address bar and press enter. The transferred size 133 | appears in the status bar at the bottom of the network tab. 134 |

    135 |
  2. 136 |
  3. 137 |

    138 | The URL must point to a web application or the home page of a 139 | website. A home page is usually the root directory of the 140 | domain, i.e., of the 141 | form https://www.example.com/ 142 | but it need not always be so. An URL of the 143 | form https://www.example.com/alice/ 144 | is also okay as long as it is a home page of some website that 145 | exists under that directory, i.e., a top-level user page within 146 | a domain is considered as a website home page. A web application 147 | is a piece of software that provides some useful functionality. 148 | The URL of a web application must point directly to the web 149 | application which may be different from the home page of the 150 | website. 151 |

    152 |
  4. 153 |
  5. 154 |

    155 | The URL must point to a page that contains useful content (e.g., 156 | an article, a manifesto page, etc.) or a list of links to such 157 | content (e.g., blog listing, catalog of websites, etc.) or a 158 | list of links of which at least one points to a page with a list 159 | of links to such content (e.g., a home page with navigation 160 | links to blog listing, feed, etc.), or provides useful 161 | functionality (e.g., a web-based game, an online currency 162 | convertor, an online calculator, etc.). 163 |

    164 |
  6. 165 |
  7. 166 |

    167 | The URL must not point merely to a page with metadata about a 168 | person or an organization (e.g., welcome page, about page, contact 169 | information page, etc. without any other content are not okay). 170 |

    171 |
  8. 172 |
  9. 173 |

    174 | The website must either be very noteworthy or some content from 175 | the website must have received at least 100 points on Reddit or 176 | Hacker News on at least one occasion. Use 177 | this 178 | Reddit link or 179 | this 180 | Hacker News link to check submissions for a website in these 181 | forums and the points the submissions have received. Replace 182 | "example.com" with the domain of the website while visiting 183 | these links above. 184 |

    185 |
  10. 186 |
187 |

188 | Note that the manual steps provided for Firefox and Chrome in the 1st 189 | point do not constitute a definitive decision criteria for membership. 190 | The compressed transfer size computation for every website is automated 191 | in refresh.js. 193 | The compressed transfer size observed by this script decides whether a 194 | website satisfies the 1st rule. The compressed transfer size observed by 195 | the script does not always exactly match what Firefox or Chrome shows. 196 | For example, this script does not count the favicon transfer size, 198 | so the transfer size that this script determines is usually a little 199 | less than what Firefox or Chrome shows. 200 |

201 |

202 | If the domain name of a website or its URL changed since one of its 203 | links received sufficient points on Reddit or Hacker News, as long as 204 | we can prove that the URL being submitted is indeed the same website 205 | from which some content received at least 100 points on Reddit or 206 | Hacker News, it is eligible to be a member of this club. For example, 207 | if the old website URL redirects to the new website or if 208 | the Wayback Machine shows that the 209 | old URL had the same content as the new one, or if it is obvious that 210 | the content that was discussed on one of these forums now resides at a 211 | new URL, then that would be sufficient proof of eligibility. 212 |

213 | 214 |

New Membership

215 |

216 | To add a website as a member to this club, first ensure that it 217 | satisfies the rules laid out in the Club Rules 218 | section. If it satisfies the club rules, then create a new issue 220 | on GitHub and provide the URL of the website. 221 |

222 | 223 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /src/urls.yaml: -------------------------------------------------------------------------------- 1 | - url: http://akkartik.name/ 2 | discussions: 3 | - date: '2017-11-11' 4 | title: The cargo cult of versioning 5 | url: https://news.ycombinator.com/item?id=15676691 6 | points: 198 7 | - date: '2018-02-27' 8 | title: Nobody's just reading your code 9 | url: https://news.ycombinator.com/item?id=16471161 10 | points: 352 11 | - date: '2019-10-18' 12 | title: 'Mu: A minimal hobbyist computing stack' 13 | url: https://news.ycombinator.com/item?id=21268252 14 | points: 105 15 | - date: '2019-11-22' 16 | title: 'Mu: Sketching out a minimal system programming language' 17 | url: https://news.ycombinator.com/item?id=21604685 18 | points: 102 19 | - date: '2020-09-17' 20 | title: Bicycles for the mind have to be see-through 21 | url: https://news.ycombinator.com/item?id=22599953 22 | points: 210 23 | - url: http://cat-v.org/ 24 | discussions: 25 | - date: '2007-06-29' 26 | title: The amazing Duff’s Device by Tom Duff! 27 | url: https://www.reddit.com/r/programming/comments/225xe 28 | points: 190 29 | - date: '2009-04-24' 30 | title: The history of UTF-8 as told by Rob Pike 31 | url: https://www.reddit.com/r/programming/comments/8f05r 32 | points: 230 33 | - date: '2009-06-20' 34 | title: S-exp vs XML, by Erik Naggum 35 | url: https://www.reddit.com/r/programming/comments/8u72o 36 | points: 260 37 | - date: '2009-07-04' 38 | title: Programming Quotes 39 | url: https://www.reddit.com/r/programming/comments/8y348 40 | points: 630 41 | - date: '2009-08-24' 42 | title: The Origin of Unix Pipes 43 | url: https://www.reddit.com/r/programming/comments/9djot 44 | points: 140 45 | - date: '2011-01-07' 46 | title: 'SOAP: The ''S'' stands for simple (not really)' 47 | url: https://news.ycombinator.com/item?id=2079631 48 | points: 246 49 | - date: '2011-03-01' 50 | title: The Origin of Unix Pipes 51 | url: https://news.ycombinator.com/item?id=2275161 52 | points: 133 53 | - date: '2011-05-01' 54 | title: 'The Basic Laws of Human Stupidity ' 55 | url: https://news.ycombinator.com/item?id=2570448 56 | points: 120 57 | - date: '2011-07-03' 58 | title: The 'intellectual property' oxymoron 59 | url: https://news.ycombinator.com/item?id=2723505 60 | points: 115 61 | - date: '2011-07-17' 62 | title: 'Plan9 has been forked: 9front' 63 | url: https://news.ycombinator.com/item?id=2772718 64 | points: 150 65 | - url: http://neverssl.com/ 66 | discussions: 67 | - date: '2017-01-10' 68 | title: NeverSSL 69 | url: https://news.ycombinator.com/item?id=13369038 70 | points: 307 71 | - date: '2019-11-02' 72 | title: NeverSSL 73 | url: https://news.ycombinator.com/item?id=21430157 74 | points: 346 75 | - url: https://10kbclub.com/ 76 | discussions: 77 | - date: '2020-12-26' 78 | title: 10 KB Club 79 | url: https://www.reddit.com/r/webdev/comments/kkcoko 80 | points: 610 81 | - date: '2020-12-28' 82 | title: 10 KB Club 83 | url: https://news.ycombinator.com/item?id=25556860 84 | points: 123 85 | - url: https://1mb.club/ 86 | discussions: 87 | - date: '2020-11-19' 88 | title: 1MB Club 89 | url: https://news.ycombinator.com/item?id=25151773 90 | points: 965 91 | - date: '2022-07-18' 92 | title: Two Years and Over 700 Websites Later 93 | url: https://news.ycombinator.com/item?id=32138631 94 | points: 140 95 | - url: https://ajroach42.com/ 96 | discussions: 97 | - date: '2019-06-25' 98 | title: Floppycasts - 1.44MB Podcasts 99 | url: https://news.ycombinator.com/item?id=20270800 100 | points: 138 101 | - url: https://augustl.com/ 102 | discussions: 103 | - date: '2013-04-20' 104 | title: Truly concurrent user interfaces 105 | url: https://www.reddit.com/r/programming/comments/1crm00 106 | points: 100 107 | - date: '2014-07-08' 108 | title: That WoW server blade 109 | url: https://www.reddit.com/r/wow/comments/2cyu9d 110 | points: 190 111 | - date: '2019-12-05' 112 | title: Linux exists only because of a happy accident 113 | url: https://www.reddit.com/r/linux/comments/e6fvj0 114 | points: 960 115 | - date: '2019-12-18' 116 | title: 'The #1 bug predictor is not technical' 117 | url: https://www.reddit.com/r/programming/comments/ec9s2o 118 | points: 320 119 | - date: '2013-07-22' 120 | title: ZeroMQ instead of HTTP, for internal services 121 | url: https://news.ycombinator.com/item?id=6086983 122 | points: 206 123 | - date: '2014-02-02' 124 | title: An immutable operating system 125 | url: https://news.ycombinator.com/item?id=7166173 126 | points: 286 127 | - date: '2014-03-22' 128 | title: JDK8 + Facebook React 129 | url: https://news.ycombinator.com/item?id=7449262 130 | points: 118 131 | - date: '2014-08-08' 132 | title: That WoW server blade 133 | url: https://news.ycombinator.com/item?id=8153781 134 | points: 104 135 | - date: '2018-04-21' 136 | title: 'Datomic: Look at all the things I''m not doing' 137 | url: https://news.ycombinator.com/item?id=16889789 138 | points: 138 139 | - url: https://blog.fefe.de/ 140 | discussions: 141 | - date: '2017-10-31' 142 | title: Monero mining malware sneaking into Android apps 143 | url: https://www.reddit.com/r/Android/comments/79uv4p 144 | points: 130 145 | - date: '2021-08-18' 146 | title: Collision in Apple's image hash method (German) 147 | url: https://www.reddit.com/r/de/comments/p6vea8 148 | points: 175 149 | - date: '2021-10-11' 150 | title: Short announcement from the ECJ 151 | url: https://www.reddit.com/r/StallmanWasRight/comments/q604fy 152 | points: 350 153 | - date: '2022-06-24' 154 | title: Epic login IPs with expired certificates 155 | url: https://www.reddit.com/r/fuckepic/comments/vjy0ap 156 | points: 180 157 | - url: https://box.matto.nl/ 158 | discussions: 159 | - date: '2019-02-16' 160 | title: We Must Revive Gopher 161 | url: https://news.ycombinator.com/item?id=19178885 162 | points: 230 163 | - url: https://carter.sande.duodecima.technology/ 164 | discussions: 165 | - date: '2019-07-21' 166 | title: Browsers are pretty good at loading pages 167 | url: https://news.ycombinator.com/item?id=20492087 168 | points: 592 169 | - date: '2021-01-11' 170 | title: My personal wishlist for a decentralized social network 171 | url: https://news.ycombinator.com/item?id=25731419 172 | points: 361 173 | - url: https://cedaei.com/ 174 | discussions: 175 | - date: '2020-08-26' 176 | title: 'Vim-Like Layer for Xorg and Wayland ' 177 | url: https://news.ycombinator.com/item?id=24280413 178 | points: 148 179 | - url: https://exozy.me/ 180 | discussions: 181 | - date: '2022-02-01' 182 | title: Installing Every Arch Package 183 | url: https://www.reddit.com/r/linux/comments/shxq12 184 | points: 810 185 | - date: '2022-02-01' 186 | title: Installing Every Arch Package 187 | url: https://news.ycombinator.com/item?id=30160191 188 | points: 271 189 | - url: https://jlelse.blog/ 190 | discussions: 191 | - date: '2019-12-15' 192 | title: Google is not a search engine, but an ad engine 193 | url: https://www.reddit.com/r/privacy/comments/eb126i 194 | points: 2050 195 | - date: '2020-11-29' 196 | title: Why is the market share of Firefox in Germany so much higher? 197 | url: https://www.reddit.com/r/firefox/comments/k35552 198 | points: 330 199 | - url: https://john-doe.neocities.org 200 | discussions: 201 | - date: '2020-11-21' 202 | title: A simple way to make HTML websites 203 | url: https://news.ycombinator.com/item?id=25170078 204 | points: 200 205 | - url: https://kerkour.fr/ 206 | discussions: 207 | - date: '2019-06-05' 208 | title: Bloom – A free and open source 'Google' 209 | url: https://news.ycombinator.com/item?id=20105567 210 | points: 747 211 | - url: https://kirjava.xyz/ 212 | discussions: 213 | - date: '2020-06-14' 214 | title: Does interactivity count? 215 | url: https://www.reddit.com/r/loadingicon/comments/h8uo7c 216 | points: 120 217 | - url: https://lawzava.com/ 218 | discussions: 219 | - date: '2020-11-29' 220 | title: State Of Linux Usability 2020 221 | url: https://www.reddit.com/r/linux/comments/k353y7 222 | points: 90 223 | - url: https://m-chrzan.xyz/ 224 | discussions: 225 | - date: '2020-10-06' 226 | title: Vim Keybindings in All CLIs 227 | url: https://www.reddit.com/r/vim/comments/j61q0y 228 | points: 140 229 | - url: https://minwiz.com/ 230 | discussions: 231 | - date: '2021-01-07' 232 | title: Starter kit for lightweight sites 233 | url: https://www.reddit.com/r/programming/comments/krooqi 234 | points: 1100 235 | - url: https://nytpu.com/ 236 | discussions: 237 | - date: '2021-03-12' 238 | title: How Git servers work, and how to keep yours secure 239 | url: https://news.ycombinator.com/item?id=26436872 240 | points: 167 241 | - url: https://ploum.net/ 242 | discussions: 243 | - date: '2013-05-17' 244 | title: The Fight for E-Clothing 245 | url: https://www.reddit.com/r/Futurology/comments/1ej0n6/ 246 | points: 310 247 | - date: '2020-07-07' 248 | title: The Story Behind an Open Source Software Un-Maintenance 249 | url: https://www.reddit.com/r/opensource/comments/hmuhz2/ 250 | points: 100 251 | - date: '2012-01-18' 252 | title: Why I'm a Pirate 253 | url: https://news.ycombinator.com/item?id=3478850 254 | points: 857 255 | - date: '2022-12-05' 256 | title: Drowning in AI Generated Garbage 257 | url: https://news.ycombinator.com/item?id=33864276 258 | points: 502 259 | - url: https://plumebio.com/ 260 | discussions: 261 | - date: '2020-08-01' 262 | title: JavaScript-free personal bio hosting 263 | url: https://news.ycombinator.com/item?id=24019540 264 | points: 123 265 | - url: https://rutar.org/ 266 | discussions: 267 | - date: '2022-09-29' 268 | title: How to build a personal webpage from scratch 269 | url: https://news.ycombinator.com/item?id=33017056 270 | points: 763 271 | - url: https://sdf.org/ 272 | discussions: 273 | - date: '2017-04-17' 274 | title: SDF - Public Access Unix System 275 | url: https://news.ycombinator.com/item?id=14134798 276 | points: 194 277 | - date: '2022-04-18' 278 | title: SDF - Public Access Unix System 279 | url: https://news.ycombinator.com/item?id=31076886 280 | points: 159 281 | - url: https://seirdy.one 282 | discussions: 283 | - date: '2021-03-21' 284 | title: A look at search engines with their own indexes 285 | url: https://www.reddit.com/r/degoogle/comments/m9hesi 286 | points: 160 287 | - date: '2021-01-31' 288 | title: WhatsApp and the Domestication of Users 289 | url: https://news.ycombinator.com/item?id=25982860 290 | points: 168 291 | - date: '2022-06-21' 292 | title: A look at search engines with their own indexes 293 | url: https://news.ycombinator.com/item?id=31820149 294 | points: 271 295 | - date: '2022-06-27' 296 | title: Two types of privacy 297 | url: https://news.ycombinator.com/item?id=31891132 298 | points: 111 299 | - url: https://sjmulder.nl/ 300 | discussions: 301 | - date: '2020-06-24' 302 | title: Text-Only Websites 303 | url: https://news.ycombinator.com/item?id=23626929 304 | points: 302 305 | - date: '2021-09-03' 306 | title: 'Windows 11: a survey of text boxes' 307 | url: https://news.ycombinator.com/item?id=28403005 308 | points: 125 309 | - url: https://susam.net/ 310 | discussions: 311 | - date: '2022-09-25' 312 | title: Peculiar Self-References 313 | url: https://www.reddit.com/r/Python/comments/xnii60 314 | points: 105 315 | - date: '2022-01-09' 316 | title: Simplicity of IRC 317 | url: https://news.ycombinator.com/item?id=29862550 318 | points: 364 319 | - date: '2022-03-12' 320 | title: Comfort of Bloated Web 321 | url: https://news.ycombinator.com/item?id=30654497 322 | points: 158 323 | - date: '2022-11-06' 324 | title: Zero Point Leet Seconds 325 | url: https://news.ycombinator.com/item?id=33491350 326 | points: 129 327 | - url: https://t0.vc/ 328 | discussions: 329 | - date: '2022-07-27' 330 | title: Fake Dog for Home Security 331 | url: https://news.ycombinator.com/item?id=32250487 332 | points: 317 333 | - url: https://tomasino.org/ 334 | discussions: 335 | - date: '2020-01-26' 336 | title: GNU Recutils 337 | url: https://news.ycombinator.com/item?id=22153665 338 | points: 505 339 | - url: https://www.cynicusrex.com/ 340 | discussions: 341 | - date: '2021-11-28' 342 | title: Web4 should run on LaTeX 343 | url: https://news.ycombinator.com/item?id=29370620 344 | points: 307 345 | - url: https://www.kj7nzl.net/ 346 | discussions: 347 | - date: '2020-11-24' 348 | title: Ham Radio Needs To Embrace The Hacker Community Now More Than Ever 349 | url: https://www.reddit.com/r/amateurradio/comments/k05lmo 350 | points: 320 351 | - date: '2021-12-12' 352 | title: Sending SMS Messages Through the ISS 353 | url: https://news.ycombinator.com/item?id=29530400 354 | points: 169 355 | - url: https://www.paritybit.ca/ 356 | discussions: 357 | - date: '2020-07-07' 358 | title: A Month-and-a-Half of Self-Hosted Email 359 | url: https://www.reddit.com/r/selfhosted/comments/hmqylf 360 | points: 80 361 | - url: https://zserge.com/ 362 | discussions: 363 | - date: '2012-10-25' 364 | title: 'CUCU: A compiler you can understand' 365 | url: https://www.reddit.com/r/programming/comments/12253z 366 | points: 130 367 | - date: '2017-07-19' 368 | title: Syntactic sugar in C - (ab)using "for" loops 369 | url: https://www.reddit.com/r/programming/comments/6obyqb 370 | points: 200 371 | - date: '2020-04-28' 372 | title: Tmux for mere mortals 373 | url: https://www.reddit.com/r/commandline/comments/g9k4sz 374 | points: 110 375 | - date: '2020-06-02' 376 | title: How to write a (toy) JVM 377 | url: https://www.reddit.com/r/java/comments/gv3l2g 378 | points: 150 379 | - date: '2020-10-12' 380 | title: World smallest office suite 381 | url: https://www.reddit.com/r/webdev/comments/j9o6yq 382 | points: 150 383 | - date: '2017-02-17' 384 | title: Partcl - a tiny command language 385 | url: https://news.ycombinator.com/item?id=13592645 386 | points: 114 387 | - date: '2020-04-10' 388 | title: Ode to J 389 | url: https://news.ycombinator.com/item?id=22831931 390 | points: 163 391 | - date: '2020-04-28' 392 | title: Tmux for mere mortals 393 | url: https://news.ycombinator.com/item?id=23003603 394 | points: 586 395 | - date: '2020-05-13' 396 | title: Linux containers in a few lines of code 397 | url: https://news.ycombinator.com/item?id=23165157 398 | points: 458 399 | - date: '2020-05-20' 400 | title: KVM host in a few lines of code 401 | url: https://news.ycombinator.com/item?id=23244709 402 | points: 158 403 | - url: https://zupzup.org/ 404 | discussions: 405 | - date: '2019-04-07' 406 | title: A Basic Web Application with Rust and Actix-web 407 | url: https://www.reddit.com/r/rust/comments/balhup 408 | points: 130 409 | --------------------------------------------------------------------------------