Repository: hackclub/site Branch: main Commit: 63b1a0792795 Files: 274 Total size: 1.3 MB Directory structure: gitextract_sca6vlk2/ ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ ├── attachment-warn.yml │ ├── caniuse-update.yml │ ├── ci.yml │ └── validate-team-json.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── AGENT.md ├── LICENSE.md ├── README.md ├── components/ │ ├── AButton.ts │ ├── analytics.tsx │ ├── announcement.tsx │ ├── announcements/ │ │ ├── amount.tsx │ │ ├── cta.tsx │ │ ├── elon.mdx │ │ ├── hcb-mobile.mdx │ │ ├── hcb-open-source.mdx │ │ ├── hcb_cta.tsx │ │ ├── holder.tsx │ │ ├── pills.tsx │ │ ├── preston-werner-2022.mdx │ │ ├── preston-werner.mdx │ │ └── relon.mdx │ ├── arcade/ │ │ ├── footer.tsx │ │ └── projects.tsx │ ├── background-image.tsx │ ├── bin/ │ │ ├── GalleryPosts.tsx │ │ ├── PartTag.module.css │ │ ├── PartTag.tsx │ │ ├── nav.tsx │ │ └── rsvp-form.tsx │ ├── bio.tsx │ ├── boardbio.tsx │ ├── color-switcher.tsx │ ├── comma.ts │ ├── directoryModal.tsx │ ├── donate/ │ │ ├── donors.json │ │ └── sponsors.tsx │ ├── dot.tsx │ ├── elon.mdx │ ├── fade-in.tsx │ ├── fiscal-sponsorship/ │ │ ├── contact.tsx │ │ ├── directory/ │ │ │ └── card.tsx │ │ ├── features.tsx │ │ ├── first/ │ │ │ ├── apply-button.tsx │ │ │ ├── features.tsx │ │ │ ├── start.tsx │ │ │ ├── stats.tsx │ │ │ └── testimonials.tsx │ │ ├── open-source.tsx │ │ ├── organization-spotlight.tsx │ │ ├── sign-in.tsx │ │ └── tooltip.tsx │ ├── flag.tsx │ ├── flex-col.tsx │ ├── footer.tsx │ ├── force-theme.ts │ ├── hackathons/ │ │ ├── features/ │ │ │ ├── marketing.tsx │ │ │ └── slack.tsx │ │ ├── keep-exploring.tsx │ │ ├── landing.tsx │ │ ├── overview.tsx │ │ ├── recap.tsx │ │ └── scrolling-hackathons.tsx │ ├── icon.tsx │ ├── index/ │ │ ├── cards/ │ │ │ ├── beest.tsx │ │ │ ├── button.tsx │ │ │ ├── card-model.tsx │ │ │ ├── clubs.tsx │ │ │ ├── fallout.tsx │ │ │ ├── flavortown.tsx │ │ │ ├── hackathons.tsx │ │ │ ├── haxidraw.tsx │ │ │ ├── hcb.tsx │ │ │ ├── hctg.tsx │ │ │ ├── horizons.tsx │ │ │ ├── jackpot.tsx │ │ │ ├── macondo.tsx │ │ │ ├── mailing-list.tsx │ │ │ ├── sinerider.tsx │ │ │ ├── slack.tsx │ │ │ ├── sleepover.tsx │ │ │ ├── sprig-console.tsx │ │ │ ├── sprig.tsx │ │ │ ├── stasis.tsx │ │ │ └── workshops.tsx │ │ ├── carousel-cards.tsx │ │ ├── carousel.tsx │ │ ├── ctas.tsx │ │ ├── events.tsx │ │ └── github.tsx │ ├── letterhead.tsx │ ├── mail-card.tsx │ ├── marquee.tsx │ ├── mention.tsx │ ├── nav.tsx │ ├── onboard/ │ │ ├── gallery-paginated.tsx │ │ ├── item.tsx │ │ ├── pagination-buttons.tsx │ │ ├── recap.tsx │ │ └── youtube-video.tsx │ ├── particles.tsx │ ├── photo.tsx │ ├── posts/ │ │ ├── emoji.tsx │ │ ├── index.tsx │ │ └── mention.tsx │ ├── press.mdx │ ├── react-reveal-compat.tsx │ ├── react-tooltip.ts │ ├── replit/ │ │ ├── scale-up.tsx │ │ └── token-instructions.tsx │ ├── scroll-hint.tsx │ ├── secret.tsx │ ├── ship/ │ │ └── why.mdx │ ├── signature.tsx │ ├── signatures.tsx │ ├── slack.tsx │ ├── slide-down.tsx │ ├── slide-up.tsx │ ├── sparkles/ │ │ ├── index.tsx │ │ └── money.tsx │ ├── stage.tsx │ ├── stat.tsx │ ├── submit.tsx │ ├── tilt.tsx │ └── winter/ │ ├── breakdown-box.tsx │ ├── breakdown.tsx │ ├── footer.tsx │ ├── info.tsx │ ├── landing.tsx │ ├── projects.tsx │ ├── recap.tsx │ └── timeline.tsx ├── eslint.config.mts ├── lib/ │ ├── cached-hcb-orgs.ts │ ├── countries.json │ ├── cta.json │ ├── dates.ts │ ├── fetcher.ts │ ├── git-info.ts │ ├── helpers.ts │ ├── members.ts │ ├── organization.ts │ ├── slackData.ts │ ├── sleep.ts │ ├── theme.ts │ ├── use-form.ts │ ├── use-has-mounted.ts │ ├── use-media.ts │ ├── use-prefers-motion.ts │ ├── use-prefers-reduced-motion.ts │ └── use-random-interval.ts ├── next.config.ts ├── package.json ├── pages/ │ ├── 404.tsx │ ├── _app.tsx │ ├── _document.tsx │ ├── acknowledged.tsx │ ├── amas/ │ │ ├── geohot.tsx │ │ ├── index.tsx │ │ ├── sal.tsx │ │ └── vitalik.tsx │ ├── api/ │ │ ├── arcade/ │ │ │ ├── hack-hour/ │ │ │ │ └── inventory.ts │ │ │ └── shop.ts │ │ ├── bin/ │ │ │ ├── gallery/ │ │ │ │ ├── posts.ts │ │ │ │ └── tags.ts │ │ │ ├── rsvp.ts │ │ │ └── wokwi/ │ │ │ ├── new/ │ │ │ │ ├── [parts].ts │ │ │ │ └── index.ts │ │ │ └── parts.ts │ │ ├── bucky.ts │ │ ├── channels/ │ │ │ └── resolve.ts │ │ ├── contribute.ts │ │ ├── first-team.ts │ │ ├── games.ts │ │ ├── github.ts │ │ ├── join.ts │ │ ├── mailing-list.ts │ │ ├── onboard/ │ │ │ ├── p/ │ │ │ │ ├── [project]/ │ │ │ │ │ └── index.ts │ │ │ │ ├── count.ts │ │ │ │ └── index.ts │ │ │ └── svg/ │ │ │ └── [board_url]/ │ │ │ ├── bottom.ts │ │ │ ├── index.ts │ │ │ └── top.ts │ │ ├── replit/ │ │ │ └── signup.ts │ │ ├── sprig-console.ts │ │ ├── stars.ts │ │ ├── steve.ts │ │ ├── stickers.ts │ │ ├── stuff.ts │ │ ├── team.ts │ │ └── winter-rsvp.ts │ ├── arcade/ │ │ └── index.tsx │ ├── bin/ │ │ ├── gallery.tsx │ │ └── prelaunch.tsx │ ├── brand.tsx │ ├── clubs.tsx │ ├── content/ │ │ ├── covid19.mdx │ │ ├── it-admins.mdx │ │ ├── sponsorship.mdx │ │ ├── sunsetting-som.mdx │ │ └── transparency/ │ │ └── may-2020.mdx │ ├── deprecated/ │ │ └── [deprecated].tsx │ ├── elon.tsx │ ├── events.tsx │ ├── fiscal-sponsorship/ │ │ ├── about.tsx │ │ ├── climate/ │ │ │ ├── [region].tsx │ │ │ └── index.tsx │ │ ├── directory/ │ │ │ ├── [category]/ │ │ │ │ ├── [region].tsx │ │ │ │ └── index.tsx │ │ │ └── index.tsx │ │ ├── first.tsx │ │ ├── index.tsx │ │ ├── mobile/ │ │ │ └── index.tsx │ │ └── open-source.tsx │ ├── hackathons/ │ │ ├── grant.tsx │ │ └── index.tsx │ ├── imprint.tsx │ ├── index.tsx │ ├── jobs/ │ │ └── index.tsx │ ├── minecraft.tsx │ ├── night.tsx │ ├── onboard/ │ │ ├── board/ │ │ │ └── [slug].tsx │ │ ├── first.tsx │ │ ├── gallery/ │ │ │ └── index.tsx │ │ └── index.tsx │ ├── opensource.tsx │ ├── philanthropy/ │ │ ├── index.tsx │ │ └── supporters.tsx │ ├── philosophy.tsx │ ├── pizza.tsx │ ├── press.tsx │ ├── preston-werner-2022.tsx │ ├── preston-werner.tsx │ ├── relon.tsx │ ├── replit.tsx │ ├── santa.tsx │ ├── sharkbank/ │ │ └── index.tsx │ ├── ship.tsx │ ├── sitemap.xml.tsx │ ├── steve.tsx │ ├── stickers.tsx │ ├── team.tsx │ └── winter.tsx ├── public/ │ ├── .well-known/ │ │ └── security.txt │ ├── acknowledged.json │ ├── bin/ │ │ ├── data-loading.js │ │ ├── index.html │ │ ├── landing/ │ │ │ ├── index.html │ │ │ ├── script.js │ │ │ └── style.css │ │ ├── landing-new/ │ │ │ ├── ascii-art.txt │ │ │ ├── gambling.js │ │ │ ├── script.js │ │ │ └── style.css │ │ ├── memes.js │ │ ├── orph/ │ │ │ ├── orph.css │ │ │ └── orph.js │ │ ├── selector/ │ │ │ ├── index.html │ │ │ ├── script.js │ │ │ └── style.css │ │ └── style/ │ │ ├── common.css │ │ ├── footer.css │ │ └── gallery.module.css │ ├── carousel.json │ ├── horizons/ │ │ └── Hypebuzz.otf │ ├── robots.txt │ ├── stickers-in-stock.html │ └── team.json ├── tsconfig.json ├── types/ │ └── mdx.d.ts └── vercel.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/dependabot.yml ================================================ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: 'bun' directory: '/' schedule: interval: 'weekly' - package-ecosystem: 'github-actions' directory: '/' schedule: interval: 'weekly' ================================================ FILE: .github/workflows/attachment-warn.yml ================================================ name: Perhaps You Should Upload To CDN Instead? on: pull_request: types: [opened, synchronize] jobs: warn: runs-on: ubuntu-slim permissions: pull-requests: write steps: - uses: actions/github-script@v9 continue-on-error: true with: # this checks via the octokit, because just using pull_requests.paths would warn on every single commit, regardless of the files changed if the PR has at least 1 attachment in it script: | // dont comment again if already commented const comments = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number }); const existingComment = comments.data.find(c => c.body.includes("Heyo, maybe upload these to a CDN instead") ); // unallowed file extensions const EXTENSIONS = [ 'png','jpg','jpeg','gif','webp', 'webm','pdf','mp4','mov','zip', ]; // paginate cause what if there's 100+ changed files, better safe than sorry const files = await github.paginate( github.rest.pulls.listFiles, { owner: context.repo.owner, repo: context.repo.repo, pull_number: context.issue.number, per_page: 100 } ); // check if any of the changed files have unallowed extension, and are not removed // only exclude removed files, since modifying/copying/etc has the same hit to the repo size as a new file const blobs = files.filter(f => { if (!f.filename.includes('.')) return false; const ext = f.filename.split('.').pop().toLowerCase(); return EXTENSIONS.includes(ext) && f.status !== 'removed'; }); if (blobs.length === 0) { // if we already commented, but the files were removed, edit the comment to kinda mark as resolved if (existingComment) { await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existingComment.id, body: `## ~~Heyo, maybe upload these to a CDN instead~~\n\nThis has been resolved now.` }); return; } return }; const prefix = `## Heyo, maybe upload these to a CDN instead\n\nImages, videos or any attachments can unnecessarily bloat the repository size. Consider uploading these files to [Hack Club CDN](https://cdn.hackclub.com/) instead, and using the CDN links instead.\n\n---\n\n### Files Detected:\n\n`; if (existingComment) { // Update existing comment with new file list await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: existingComment.id, body: `${prefix}${blobs.map(b => `- \`${b.filename}\``).join('\n')}` }); return; } // create comment if there are any attachments await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: `${prefix}${blobs.map(b => `- \`${b.filename}\``).join('\n')}` }); ================================================ FILE: .github/workflows/caniuse-update.yml ================================================ name: Update Browserslist database on: workflow_dispatch: schedule: - cron: '0 2 1,15 * *' permissions: contents: write pull-requests: write jobs: update-browserslist-database: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 0 - name: Configure git run: | git config --global user.email "action@github.com" git config --global user.name "GitHub Action" - name: Update Browserslist database and create PR if applies uses: c2corg/browserslist-update-action@v2 with: github_token: ${{ secrets.GITHUB_TOKEN }} branch: browserslist-update base_branch: main commit_message: 'build: update Browserslist db' title: 'build: update Browserslist db' body: Auto-generated by [browserslist-update-action](https://github.com/c2corg/browserslist-update-action/). Caniuse database has been updated. Review changes, merge this PR, and be merry. ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: - push - pull_request jobs: lint: name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bun run lint format: name: Format runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bun run format:check ================================================ FILE: .github/workflows/validate-team-json.yml ================================================ name: Validate Team JSON on: push: paths: - 'public/team.json' pull_request: paths: - 'public/team.json' jobs: validate: name: Validate team.json runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Validate JSON format run: | if ! jq empty public/team.json 2>/dev/null; then echo "Error: team.json is not valid JSON" exit 1 fi echo "✓ team.json is valid JSON" ================================================ FILE: .gitignore ================================================ .now .env* .next node_modules .DS_Store public/sitemap.xml .vercel .vscode yarn-error.log bun.lockb .idea .yarn .yarnrc.yml .env*.local tsconfig.tsbuildinfo next-env.d.ts ================================================ FILE: .prettierignore ================================================ .next ================================================ FILE: .prettierrc ================================================ { "singleQuote": true, "trailingComma": "none", "arrowParens": "avoid", "printWidth": 80, "semi": false } ================================================ FILE: AGENT.md ================================================ # AGENT.md - Hack Club Site Development Guide ## Commands - **Dev**: `bun run dev` (start development server) - **Build**: `bun run build` (production build) - **Lint**: `bun run lint` (Next.js ESLint) - **Format**: `bun run format` (Prettier formatting) - **Start**: `bun run start` (production server) - **Test**: No test framework configured ## Code Style - **Imports**: Use relative imports (`../components/nav`), Theme UI components (`{ Box, Text }`) - **Formatting**: Single quotes, no semicolons, no trailing commas, 80 char width - **Components**: Functional components with destructured props, default exports - **Styling**: Theme UI `sx` prop for styling, styled components with @emotion/styled - **Types**: TypeScript enabled but strict mode off, prefer implicit typing - **Naming**: camelCase for variables/functions, PascalCase for components ## Architecture - Next.js app with pages/ directory structure - MDX support for content pages - Theme UI for consistent styling with Hack Club theme - Components in components/ directory, modular cards in components/index/cards/ - Static assets in public/ - Configuration in next.config.mjs includes essential redirects/rewrites ================================================ FILE: LICENSE.md ================================================ _Code under MIT License, assets may not be re-used or re-distributed._ ### MIT License Copyright 2026 The Hack Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================

Hack Club logo

Hack Club's Site (v3)

The source code for hackclub.com

Hack Club's new website. This codebase is what runs on [hackclub.com](https://hackclub.com). For new developers getting started, run the following in your terminal: 1. Download the code to your computer: ```bash git clone https://github.com/hackclub/site && cd site ``` 2. Install dependencies: ```bash bun install ``` 3. Start running the website on your computer: ```bash bun run dev ``` 4. Open up your web browser and go to [localhost:3000](http://localhost:3000) > [!NOTE] > There are a number of redirects and rewrites essential to the website's functionality, which you can see in [next.config.ts](./next.config.ts). Powered by [Next.js] with [MDX], [Theme UI], & [Hack Club Theme]. Code under MIT License, assets may not be re-used or re-distributed. ---

Building hackclub.com

Join us in building Hack Club's homepage and show new hackers what Hack Club could be for them 💖. See something that could be better? Make a PR! Have an easter egg idea? Make a PR! Is the site missing something? Make a PR! _(Do you see a trend? :))_ If you need to add content to the site, here's how you can:
Create a new card Screenshot of the Sprig card Most things on the homepage are cards, modular components that can easily be added and removed according to relevancy to Hack Clubbers. There are 3 main sections: connection, open-source, and IRL community. Most new cards will likely fall within the first two sections! First, you can create a new file under [components/index/cards](components/index/cards/) with the name of your new event/project. Next add `import CardModel from './card-model'` and add whatever you want :) Finally, use a `` component (`import Buttons from './button'`) to highlight call-to-action buttons. If it's the main button, use the primary prop to add a background color! Your challenge: try and make the card as unique as possible, like a mini poster! Not sure where to start? Look at other cards on the page :)
Add to the carousel Screenshot of a carousel section If there's a Hack Club or Hack Club community-led project (past or present) that Hack Clubbers can get involved in, please add it to [public/carousel.json](public/carousel.json) and add your card to the end of the json file. An example looks like this: ```json { "background": "dark", "titleColor": "white", "descriptionColor": "white", "title": "Hackers Wanted", "description": "Our open love letter to hackers", "img": "https://a.slack-edge.com/production-standard-emoji-assets/14.0/apple-large/1f4bb@2x.png", "link": "/hackers-wanted" } ```
Every week, thousands of people visit hackclub.com. What story do you want to tell? _Have questions? Join us in [#hackclub-site-dev](https://hackclub.slack.com/archives/C036BTDGP43) and to learn more about the style guide at Hack Club check [this](https://hackclub.com/brand/) out_ --- Hack Club, 2026. MIT License. [next.js]: https://nextjs.org [mdx]: https://mdxjs.com [theme ui]: https://theme-ui.com [hack club theme]: https://theme.hackclub.com ================================================ FILE: components/AButton.ts ================================================ import { Button } from 'theme-ui' export const AButton = Button as any ================================================ FILE: components/analytics.tsx ================================================ import Script from 'next/script' const Analytics = () => (