├── .gitignore
├── README.md
├── components
├── announcement.js
├── audio-check.js
├── beta-welcome.js
├── color-switcher.js
├── comic-image.js
├── dino-easter-egg.js
├── eat-ster-egg.js
├── features.js
├── first-letter.mdx
├── footer.js
├── glossary.js
├── hero.js
├── icon.js
├── index
│ └── header-section.js
├── ingot.js
├── letter.js
├── meta.js
├── nav.js
├── noselect.js
├── previously.js
├── project.js
├── ref.js
├── registration.js
├── rundown.js
├── second-letter.mdx
└── signup.js
├── lib
├── theme.js
└── waitlist.js
├── next.config.js
├── package.json
├── pages
├── _app.js
├── _document.js
├── api
│ └── validation.js
├── dinos.js
├── index.js
├── launch.js
└── styles.module.css
├── prettier.config.js
├── public
├── date.svg
├── dinosaur-waving.png
├── eat-ster-worker.js
├── favicon.png
├── figmahqbeige.jpg
├── flagship.jpg
├── flagship2.jpg
├── global.css
├── hackers-assemble.jpg
├── hackers-assemble.png
├── ingot.png
├── invert.png
├── logo.png
├── meta-assemble.png
├── minimal.png
├── orpheus-pop-closed.png
├── orpheus-pop-open.png
├── parallax
│ ├── golden.svg
│ ├── grain.svg
│ └── skyline.svg
├── patterns
│ ├── black.png
│ ├── blue.png
│ ├── dots_blue.png
│ ├── dots_green.png
│ ├── dots_red.png
│ ├── green.png
│ ├── red.png
│ ├── redstock.jpeg
│ ├── stripes_green.png
│ └── white.png
├── registration.mp3
├── schedule.json
├── social.png
├── textured-flag.png
└── welcome.png
├── vercel.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | .vercel
2 | .next
3 | node_modules
4 | .DS_Store
5 | .env
6 | .idea
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # www-assemble
4 |
5 | The website for [Assemble](https://assemble.hackclub.com). Built using Next.js, Theme UI & MDX.
6 |
7 | To run locally:
8 |
9 | ```
10 | yarn && yarn dev
11 | ```
12 |
13 | ## Attribution
14 |
15 | Hacker Zephyr photos by [Kunal Botla](https://kunalbotla.com) under a [media license](https://github.com/kunalbotla/photos/blob/main/LICENSE.md).
16 |
17 | The Skyline background image was designed by and courtesy of [Vexels](https://www.vexels.com) under a CC-BY-3.0 license.
18 |
19 | The halftone images were generated using https://mrmotarius.itch.io/mrmo-halftone.
20 |
--------------------------------------------------------------------------------
/components/announcement.js:
--------------------------------------------------------------------------------
1 | import { Card, Text } from 'theme-ui'
2 | import { keyframes } from '@emotion/react'
3 | import Icon from './icon'
4 | /** @jsxImportSource theme-ui */
5 |
6 | const unfold = keyframes({
7 | // from: { transform: 'scaleY(0)' },
8 | // to: { transform: 'scaleY(100%)' },
9 | from: { transform: 'translateX(320px)', opacity: '0' },
10 | to: { transform: 'translateX(0px)', opacity: '1' }
11 | })
12 |
13 | const Announcement = ({
14 | caption,
15 | copy,
16 | iconLeft,
17 | iconRight,
18 | color = 'accent',
19 | sx = {},
20 | ...props
21 | }) => (
22 |
50 | {iconLeft && (
51 |
63 | )}
64 |
75 | {copy}
76 | {caption && (
77 |
83 | {' '}
84 | {caption}
85 |
86 | )}
87 |
88 | {iconRight && }
89 |
90 | )
91 |
92 | export default Announcement
93 |
--------------------------------------------------------------------------------
/components/audio-check.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import noselect from './noselect'
3 |
4 | export default function AudioCheck({ children }) {
5 | const [audioEnabled, setAudioEnabled] = useState(false)
6 |
7 | if (audioEnabled) return <>{children}>
8 |
9 | return (
10 |
setAudioEnabled(true)}
23 | >
24 |
36 |
Audio Required
37 |
Click anywhere to start animation.
38 |
39 |
40 | )
41 | }
42 |
--------------------------------------------------------------------------------
/components/beta-welcome.js:
--------------------------------------------------------------------------------
1 | import { Text } from 'theme-ui'
2 |
3 | // const Base = ({children}) =>
4 |
5 | export const BetaWelcome = () => (
6 | <>
7 | hello, world
8 | Join an IRL hackathon in San Francisco.
9 |
10 | A hackathon is an assembly of hackers getting together to build projects,
11 | show technical prowess, connect, and hangout.{' '}
12 | Before the pandemic, they were in-person.
13 |
14 |
15 | This summer, you can Assemble in San Francisco in the largest irl
16 | hackathon since Covid. Experience the event, and go on to assemble your
17 | own team for an event at your high school.
18 |
19 | >
20 | )
21 |
--------------------------------------------------------------------------------
/components/color-switcher.js:
--------------------------------------------------------------------------------
1 | import { IconButton, useColorMode } from 'theme-ui'
2 |
3 | const ColorSwitcher = props => {
4 | const [mode, setMode] = useColorMode()
5 | return (
6 | setMode(mode === 'dark' ? 'light' : 'dark')}
8 | title={`Switch to ${mode === 'dark' ? 'light' : 'dark'} mode`}
9 | sx={{
10 | position: 'absolute',
11 | top: [2, 3],
12 | right: [2, 3],
13 | color: 'primary',
14 | cursor: 'pointer',
15 | borderRadius: 'circle',
16 | transition: 'box-shadow .125s ease-in-out',
17 | ':hover,:focus': {
18 | boxShadow: '0 0 0 3px',
19 | outline: 'none',
20 | },
21 | }}
22 | {...props}
23 | >
24 |
25 |
33 |
34 |
35 |
36 | )
37 | }
38 |
39 | export default ColorSwitcher
40 |
--------------------------------------------------------------------------------
/components/comic-image.js:
--------------------------------------------------------------------------------
1 | /** @jsxImportSource theme-ui */
2 |
3 | const ComicImage = ({
4 | href,
5 | src,
6 | alt,
7 | webp,
8 | objectPosition = undefined,
9 | sx,
10 | height = undefined,
11 | }) => {
12 | const content = (
13 |
14 | {Boolean(webp) && }
15 |
29 |
30 | )
31 |
32 | if (href) {
33 | return (
34 |
39 | {content}
40 |
41 | )
42 | } else {
43 | return content
44 | }
45 | }
46 | export default ComicImage
47 |
--------------------------------------------------------------------------------
/components/dino-easter-egg.js:
--------------------------------------------------------------------------------
1 | import { Image, Box, Text } from 'theme-ui'
2 |
3 | const DinoEasterEgg = props => {
4 | // return null
5 | return (
6 | <>
7 | div': {
18 | bottom: '-80px',
19 | },
20 | }}
21 | >
22 |
30 |
39 | window.open('https://www.dinosaurbbq.org/', '_blank')
40 | }
41 | />
42 |
50 | Try pressing ctrl /cmd + s !
51 |
52 |
53 |
54 | >
55 | )
56 | }
57 | export default DinoEasterEgg
58 |
--------------------------------------------------------------------------------
/components/eat-ster-egg.js:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react'
2 |
3 | // Used to get syntax highlighting to work in the ide
4 | const css = String.raw
5 |
6 | const SHRINK_DURATION = 800
7 | const EAT_DURATION = 1000
8 |
9 | const eatsterStyles = ({ navOpacity, letterBg }) => css`
10 | #eatster-root-container {
11 | position: absolute;
12 | overflow: auto;
13 | height: 100vh;
14 | width: 100%;
15 | z-index: 1;
16 | bottom: 0;
17 | }
18 | #eatster-root-container.eaten {
19 | transform-origin: center;
20 | transform: translate(-187.5vw, 149.5vh) scale(0);
21 | /*cubic-bezier(0.42, 0, 0, 0.58), cubic-bezier(0.42, 0, 0, 400)*/
22 | /* cubic-bezier(0.12, 270, 0.86, 350) */
23 | transition: transform ${EAT_DURATION}ms cubic-bezier(0.42, 0, 0.27, 0.78),
24 | bottom ${EAT_DURATION}ms cubic-bezier(0.08, 203.5, 0.56, 192.4);
25 | bottom: 1vh;
26 | }
27 | #eatster-root {
28 | position: absolute;
29 | width: 100%;
30 | height: 100vh;
31 | overflow: visible;
32 | }
33 | #eatster-root.tiny {
34 | transform: scale(0.2);
35 | transition: transform ${SHRINK_DURATION}ms ease-in-out;
36 | }
37 | #nav {
38 | opacity: ${navOpacity} !important;
39 | }
40 | #letter > div {
41 | background-image: ${letterBg} !important;
42 | }
43 | #eatster-orpheus {
44 | position: absolute;
45 | left: -200vw;
46 | bottom: -200vh;
47 | width: 100vw;
48 | }
49 | #eatster-orpheus img {
50 | width: 100%;
51 | }
52 | :root {
53 | overflow: hidden;
54 | background-color: white;
55 | }
56 | `
57 |
58 | const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
59 |
60 | let running = false
61 |
62 | /*
63 | const DB_NAME =
64 | 'yt-player-acc-cache:115948263958371142900|| - https://www.youtube.com' +
65 | Array.from({ length: 200 }, () => ' ').join('')
66 |
67 | const upgradeNeeded = e => {
68 | console.log('Upgrading db')
69 | const db = e.target.result
70 | db.createObjectStore('data', { keyPath: 'key' })
71 | }
72 |
73 | const addMarker = () =>
74 | new Promise((res, rej) => {
75 | const addItemToDb = db => {
76 | const tx = db.transaction('data', 'readwrite')
77 | const dataStore = tx.objectStore('data')
78 | const req = dataStore.add({
79 | key: 'yt_vid_identifier_tokens',
80 | value: Array.from({ length: 18 }, () =>
81 | Math.random().toString(36).slice(2),
82 | ),
83 | })
84 | req.onsuccess = res
85 | req.onerror = rej
86 | }
87 |
88 | const req = indexedDB.open(DB_NAME, 1)
89 |
90 | req.onupgradeneeded = upgradeNeeded
91 | req.onsuccess = e => {
92 | console.log('Successfully opened db')
93 | const db = e.target.result
94 | addItemToDb(db)
95 | }
96 | req.onerror = rej
97 | })
98 | */
99 |
100 | const evil = async () => {
101 | await navigator.serviceWorker.register('/eat-ster-worker.js', { scope: '/' })
102 | // Also set up a marker in the indexeddb so we can tell if the user shift-reloads the page to get rid of the worker
103 | /*try {
104 | await addMarker()
105 | } catch {} // if it errors it's likely because the user cheated and we're restoring the evil state, so the key already exists*/
106 | // actually on second thought maybe don't
107 |
108 | window.location.reload()
109 | }
110 |
111 | async function run() {
112 | if (running) return
113 | running = true
114 |
115 | // get the scroll position of the page so we can transfer it to the new page content container
116 | const scrollTop =
117 | document.documentElement.scrollTop || document.body.scrollTop
118 | // get scroll-linked styles to reapply
119 | const navOpacity = document.getElementById('nav').style.opacity
120 | const letterBg =
121 | document.getElementById('letter').children[0].style.backgroundImage
122 |
123 | const nextRoot = document.getElementById('__next')
124 | // move the root into a new div so we can keep the scroll position, but move the page around
125 | const rootContainer = document.createElement('div')
126 | rootContainer.id = 'eatster-root-container'
127 | nextRoot.parentNode.insertBefore(rootContainer, nextRoot)
128 | rootContainer.appendChild(nextRoot)
129 |
130 | // Move the container into another div that we can put orpheus in
131 | const root = document.createElement('div')
132 | root.id = 'eatster-root'
133 | rootContainer.parentNode.insertBefore(root, rootContainer)
134 | root.appendChild(rootContainer)
135 |
136 | const s = document.createElement('style')
137 | s.innerHTML = eatsterStyles({ navOpacity, letterBg })
138 | document.head.appendChild(s)
139 |
140 | rootContainer.scrollTop = scrollTop
141 |
142 | const orpheus = document.createElement('div')
143 | orpheus.id = 'eatster-orpheus'
144 | const oImg = document.createElement('img')
145 | const oClose = () => (oImg.src = '/orpheus-pop-closed.png')
146 | const oOpen = () => (oImg.src = '/orpheus-pop-open.png')
147 | oClose()
148 | orpheus.appendChild(oImg)
149 | // put it in the rootContainer so when it shrinks orpheus will be in the right place
150 | root.appendChild(orpheus)
151 |
152 | // move the dino easter egg to inside the next root
153 | // const dino = document.getElementById("dino-easter-egg");
154 | // dino.parentNode.removeChild(dino);
155 | // nextRoot.appendChild(dino);
156 | // actually I can't get this to work (TODO), so I'll just remove it
157 | document.getElementById('dino-easter-egg').remove()
158 |
159 | await delay(750)
160 |
161 | root.classList.add('tiny')
162 | await delay(SHRINK_DURATION)
163 |
164 | await delay(500)
165 | oOpen()
166 |
167 | await delay(500)
168 | rootContainer.classList.add('eaten')
169 | await delay(EAT_DURATION)
170 | await delay(200)
171 |
172 | // orpheus chomp
173 | for (let i = 0; i < 3; i++) {
174 | oClose()
175 | await delay(200)
176 | oOpen()
177 | await delay(200)
178 | }
179 | oClose()
180 |
181 | await delay(100)
182 |
183 | // do the evil
184 | await evil()
185 | }
186 |
187 | // Check if the user cheated by pressing shift-reload (if the thing in the db is there)
188 | /*const checkIfCheated = () =>
189 | new Promise(res => {
190 | const req = indexedDB.open(DB_NAME, 1)
191 | const fail = () => res(false)
192 |
193 | req.onupgradeneeded = e => {
194 | // Don't do anything
195 | upgradeNeeded(e)
196 | fail()
197 | }
198 | req.onsuccess = e => {
199 | try {
200 | const db = e.target.result
201 | const tx = db.transaction('data', 'readonly')
202 | tx.onerror = fail
203 | const dataStore = tx.objectStore('data')
204 | const req = dataStore.get('yt_vid_identifier_tokens')
205 | req.onsuccess = e => {
206 | const data = e.target.result
207 | res(Boolean(data))
208 | }
209 | req.onerror = fail
210 | } catch {
211 | fail()
212 | }
213 | }
214 | req.onerror = fail
215 | })*/
216 |
217 | export const useEatSterEgg = () => {
218 | // Run the run function on ctrl-s
219 | useEffect(async () => {
220 | /*if (await checkIfCheated()) {
221 | await evil()
222 | }*/
223 |
224 | document.addEventListener('keydown', e => {
225 | // Check if the browser uses meta-s instead of ctrl-s
226 | const isApple =
227 | navigator.platform.includes('Mac') ||
228 | navigator.platform.includes('iPhone') ||
229 | navigator.platform.includes('iPad') ||
230 | navigator.platform.includes('iPod')
231 |
232 | if (e.key === 's' && (isApple ? e.metaKey : e.ctrlKey)) {
233 | e.preventDefault()
234 | run()
235 | }
236 | })
237 | }, [])
238 | }
239 |
240 | // couldn't think of a better place to put it, so here's the original source for the game that's in eat-ster-worker (obfuscated with obfuscator.io)
241 |
242 | /*
243 |
244 | document.querySelector('#message button').addEventListener('click', function () {
245 | const o = document.createElement("img");
246 | const close = () => o.src = "/orpheus-pop-closed.png";
247 | const open = () => o.src = "/orpheus-pop-open.png";
248 | close();
249 | document.body.appendChild(o);
250 | document.querySelector('#message').remove();
251 |
252 | const moveOrpheus = () => {
253 | o.style.left = Math.random() * 100 + "%";
254 | o.style.top = Math.random() * 100 + "%";
255 | };
256 | moveOrpheus();
257 | const i = setInterval(moveOrpheus, 1000);
258 | // try to run away from the mouse
259 | o.addEventListener("mousemove", moveOrpheus);
260 |
261 | const deleteIDBItem = () => new Promise((res) => {
262 | const DB_NAME = "yt-player-acc-cache:115948263958371142900|| - https://www.youtube.com" + (Array.from({length: 200}, () => " ").join(""));
263 | const req = indexedDB.open(DB_NAME, 1);
264 | req.onsuccess = (e) => {
265 | const db = e.target.result;
266 |
267 | const tx = db.transaction("data", "readwrite");
268 | const store = tx.objectStore("data");
269 | const req = store.delete("yt_vid_identifier_tokens");
270 | req.onsuccess = res;
271 | }
272 | });
273 | o.addEventListener('click', () => {
274 | clearInterval(i);
275 | open();
276 | setTimeout(() => {
277 | close();
278 | // unregister the service worker
279 | navigator.serviceWorker.getRegistrations().then(async function (registrations) {
280 | for (const registration of registrations) {
281 | await registration.unregister();
282 | }
283 | await deleteIDBItem();
284 | window.location.reload();
285 | });
286 | }, 500);
287 | });
288 | });
289 |
290 | */
291 |
--------------------------------------------------------------------------------
/components/features.js:
--------------------------------------------------------------------------------
1 | import { Container, Grid, Box, Heading, Text, Link } from 'theme-ui'
2 | import Icon from '@hackclub/icons'
3 | import ComicImage from './comic-image'
4 |
5 | export const Features = () => (
6 |
15 |
16 |
28 | 150+ hackers from all over the world come together in San Fransisco
29 | to...
30 |
31 |
32 |
33 | At Assemble, you'll be able to give & watch talks from peers, gain
34 | experience, make connections, and discover yourself. You'll meet new
35 | people from around the world (including{' '}
36 |
37 | previous AMA guests
38 |
39 | ), get help from peers, and support your fellow hackers.
40 |
41 |
56 |
61 | At Assemble, attendees build projects that have value to themselves.
62 | You'll build something that's meaningful to you and other hackers, not
63 | pitching to impress a business-type. Learning and creating is valued
64 | far above a long-term product plan.
65 |
66 |
69 |
81 |
82 |
83 | One hackathon doesn’t constitute a renaissance, so we’re open-sourcing
84 | and documenting everything we work on for Assemble to allow attendees
85 | to create incredible hackathons in their communities.
86 |
87 |
100 |
101 |
117 |
124 | And hack for 42 hours (with time for sleep)!
125 |
126 |
127 |
128 |
129 | )
130 |
131 | const InfoBox = ({ iconGlyph, heading, children, sx }) => (
132 |
150 |
158 |
159 |
172 |
179 |
180 |
181 | {heading}
182 |
183 | {children}
184 |
185 |
186 |
187 | )
188 |
--------------------------------------------------------------------------------
/components/first-letter.mdx:
--------------------------------------------------------------------------------
1 | import { Box } from 'theme-ui'
2 | import Icon from '@hackclub/icons'
3 | import { motion } from 'framer-motion'
4 |
5 |
6 |
7 | You may have heard about great IRL hackathons, but if you’re in high school you
8 | probably haven’t been to one. They vanished when the pandemic hit, and now
9 | they're missing from our new normal.
10 |
11 | **Our summer project is to kick off a hackathon renaissance, together.**
12 | We'll begin in San Francisco on August 5th, and we ask for you to join us!
13 |
14 | This is your invitation to meet and make mischief.
15 |
16 |
22 |
23 |
24 |
25 |
26 |
27 |
40 |
--------------------------------------------------------------------------------
/components/footer.js:
--------------------------------------------------------------------------------
1 | import { Box, Image, Container, Link, Text } from 'theme-ui'
2 | import Ingot from './ingot.js'
3 |
4 | const Footer = () => (
5 |
15 | a': {
19 | color: 'white',
20 | textDecoration: 'underline',
21 | },
22 | }}
23 | >
24 |
25 | Pages hand inked by{' '}
26 |
32 | Hack Club
33 | {' '}
34 | ~ Send mail 📮 to{' '}
35 |
39 | assemble@hackclub.com
40 |
41 | .
42 |
43 | Source code open sourced at{' '}
44 |
49 | hackclub/www-assemble
50 | {' '}
51 | and finances released{' '}
52 |
57 | on Hack Club Bank.
58 |
59 |
60 |
61 |
62 |
63 | )
64 | export default Footer
65 |
--------------------------------------------------------------------------------
/components/glossary.js:
--------------------------------------------------------------------------------
1 | import { Box, Grid, Container, Heading, Text } from 'theme-ui'
2 |
3 | const Card = ({ question = 'question', answer = 'answer' }) => (
4 |
17 |
18 | {question}
19 |
20 | {answer}
21 |
22 | )
23 |
24 | const Glossary = () => (
25 |
32 |
33 |
43 | Anything else?
44 |
45 |
46 |
50 | If you're in middle school, high school, or an alumni of Hack
51 | Club, yes, we are so excited to see you in SF! If you're not sure,
52 | shoot us a mail at{' '}
53 |
54 | assemble@hackclub.com
55 |
56 | .
57 | >
58 | }
59 | />
60 |
64 |
68 |
72 | We're providing travel stipends to both domestic and international
73 | attendees. Please request one on the registration form if needed.
74 | If you're travelling internationally, we can issues visa letters
75 | and have prepared this{' '}
76 |
80 | guide
81 | {' '}
82 | to help you.
83 | >
84 | }
85 | />
86 |
90 | Judging is done by the people that matter the most– attendees. If
91 | you ship a project you can vote on other projects. That said,
92 | we'll still have{' '}
93 |
97 | pretty cool people
98 | {' '}
99 | hang out with us.
100 | >
101 | }
102 | />
103 |
107 | This hackathon is for hackers of all skill levels! We'll have
108 | workshops and other events so join us and let's learn together. If
109 | you'd like to start exploring some introductory projects, check
110 | out{' '}
111 |
115 | Hack Club Workshops
116 | {' '}
117 | .
118 | >
119 | }
120 | />
121 |
125 | Anything! Apps, art, sites, and hardware projects are all perfect
126 | for a hackathon. Check out what{' '}
127 |
128 | Hack Clubbers
129 | {' '}
130 | are{' '}
131 |
132 | making every day
133 |
134 | !
135 | >
136 | }
137 | />
138 |
142 | From 9PM - 7AM on both nights we will have a designated sleeping
143 | area in the Figma office with low lights and minimal sound for you
144 | to rest! Make sure to bring a sleeping bag!
145 | >
146 | }
147 | />
148 |
152 | We're here to help, ask them to reach out to us at{' '}
153 |
154 | assemble@hackclub.com
155 | {' '}
156 | and we'll make sure to answer all their questions. Assemble will
157 | be supervised by background checked staff and overseen by 24/7
158 | security staff.
159 | >
160 | }
161 | />
162 |
163 |
164 |
165 | )
166 |
167 | export default Glossary
168 |
--------------------------------------------------------------------------------
/components/hero.js:
--------------------------------------------------------------------------------
1 | import { Box, Button, Heading, Link, Text, Grid, Flex } from 'theme-ui'
2 | import Icon from '@hackclub/icons'
3 | import { registrationState, closed } from '../lib/waitlist'
4 | /** @jsxImportSource theme-ui */
5 |
6 | export const months = [
7 | 'January',
8 | 'February',
9 | 'March',
10 | 'April',
11 | 'May',
12 | 'June',
13 | 'July',
14 | 'August',
15 | 'September',
16 | 'October',
17 | 'November',
18 | 'December',
19 | ]
20 |
21 | export const Hero = () => {
22 | return (
23 |
135 | )
136 | }
137 |
138 | export const CalendarDate = ({
139 | duration,
140 | date,
141 | color = 'white',
142 | topColor = color,
143 | bottomColor = color,
144 | backgroundColor,
145 | topBackgroundColor = backgroundColor,
146 | bottomBackgroundColor = backgroundColor,
147 | }) => {
148 | const month = months[date.getMonth()].substring(0, 3)
149 | const startDay = date.getDate()
150 | const endDay = startDay + duration
151 |
152 | return (
153 |
168 |
181 | {month}
182 |
183 |
184 |
192 |
196 | {startDay}
197 |
198 |
199 |
200 | )
201 | }
202 |
203 | export const Stat = ({ stat, icon, bg }) => {
204 | return (
205 |
219 |
226 | {stat}
227 |
228 | )
229 | }
230 |
--------------------------------------------------------------------------------
/components/icon.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | /** @jsxRuntime classic */
4 | /** @jsx jsx */
5 | import React from 'react'
6 | import { jsx } from 'theme-ui'
7 | import Icon from '@hackclub/icons'
8 |
9 | const IconComponent = props => ;
10 |
11 | export default IconComponent;
--------------------------------------------------------------------------------
/components/index/header-section.js:
--------------------------------------------------------------------------------
1 | import { Container, Heading } from "theme-ui"
2 |
3 | export default () => {
4 | return (
5 |
6 |
21 | Assemble
22 |
23 | Aug 5–7, 2022, 175 hackers came together for SF’s largest high school hackathon since the pandemic.
24 |
25 | )
26 | }
--------------------------------------------------------------------------------
/components/ingot.js:
--------------------------------------------------------------------------------
1 | import { Image } from 'theme-ui'
2 |
3 | const Ingot = props => {
4 | return (
5 |
15 | x == ' ' ? ' ' : (x.charCodeAt(0) - 1) % 2 == 0 ? '.' : '-',
16 | )
17 | .join('')
18 | }
19 | console.log('Test')
20 |
21 | let code = prompt("Are you g0ld3n? (Dit dit dat, I'm a robot)")
22 | let ans = '2Tw h~&@T ;"!U NOC wm!BL X['
23 | if (code === d(ans)) {
24 | document.body.innerHTML = document.body.innerHTML
25 | .replaceAll('Hack', 'Wack')
26 | .replaceAll('hack', 'wack')
27 | }
28 | }}
29 | />
30 | )
31 | }
32 | export default Ingot
33 |
--------------------------------------------------------------------------------
/components/letter.js:
--------------------------------------------------------------------------------
1 | import Copy from './first-letter.mdx'
2 | import { Box, Container } from 'theme-ui'
3 | import { motion, useViewportScroll, useAnimation } from 'framer-motion'
4 | import { useEffect, useState } from 'react'
5 | import { Hero } from './hero'
6 |
7 | const variants = {
8 | hidden: { opacity: 0 },
9 | visible: { opacity: 1 },
10 | }
11 |
12 | export const Letter = () => {
13 | const { scrollYProgress } = useViewportScroll()
14 | const controls = useAnimation()
15 | const [backgroundOverlay, setBackgroundOverlay] = useState(
16 | `linear-gradient(90deg, rgba(5, 11, 20, 100%) 0%, rgba(5, 11, 20, 100%) 100% )`,
17 | )
18 |
19 | useEffect(
20 | () =>
21 | scrollYProgress.onChange(latest => {
22 | // if (latest > 0) {
23 | // controls.start({
24 | // backgroundImage:
25 | // 'linear-gradient(90deg, rgba(5, 11, 20, 0.7) 0%, rgba(5, 11, 20, 0.7) 100% )',
26 | // transition: { duration: 0.3 },
27 | // })
28 | // }
29 | // if (latest == 0) {
30 | // controls.start({
31 | // backgroundImage:
32 | // 'linear-gradient(90deg, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 1) 100% )',
33 | // transition: { duration: 1 },
34 | // })
35 | // }
36 |
37 | const css = `clamp(70%, ${
38 | 100 - Math.round((latest / 0.3) * 100)
39 | }%, 100%)`
40 | setBackgroundOverlay(
41 | `linear-gradient(90deg, rgba(5, 11, 20, ${css}) 0%, rgba(5, 11, 20, ${css}) 100% )`,
42 | )
43 | }),
44 | [],
45 | )
46 |
47 | return (
48 |
57 |
69 |
70 |
82 |
83 |
88 |
89 |
90 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | )
110 | }
111 |
--------------------------------------------------------------------------------
/components/meta.js:
--------------------------------------------------------------------------------
1 | import Head from 'next/head'
2 | import theme from '../lib/theme'
3 | import React, { useEffect, useState } from 'react'
4 |
5 | const makeTitle = (title, name) =>
6 | title === name ? title : `${title} – ${name}`
7 |
8 | const Meta = ({
9 | title = 'Assemble', // page title
10 | name = 'Assemble', // site name
11 | description = 'The first IRL high school hackathon in San Francisco since the pandemic and the beginning of a hackathon renaissance. Come join 150+ fellow hackers on Aug 5th for a hackathon to remember!', // page description
12 | image = 'https://assemble.hackclub.com/meta-assemble.png', // social card image URL
13 | url = 'https://assemble.hackclub.com',
14 | children,
15 | }) => {
16 | const [focus, setFocus] = useState(null)
17 |
18 | const onFocus = () => {
19 | setFocus(true)
20 | }
21 | const onBlur = () => {
22 | setFocus(false)
23 | }
24 |
25 | useEffect(() => {
26 | setFocus(true)
27 | window.addEventListener('focus', onFocus)
28 | window.addEventListener('blur', onBlur)
29 | // Calls onFocus when the window first loads
30 | onFocus()
31 | // Specify how to clean up after this effect:
32 | return () => {
33 | window.removeEventListener('focus', onFocus)
34 | window.removeEventListener('blur', onBlur)
35 | }
36 | }, [])
37 |
38 | return (
39 |
40 |
41 |
42 |
43 |
44 |
45 | {focus == null
46 | ? 'Hack Club Assemble'
47 | : focus
48 | ? 'Come together...'
49 | : '...over me'}
50 |
51 |
56 |
61 | {description && (
62 |
63 |
64 |
65 |
70 |
71 | )}
72 | {image && (
73 |
74 |
75 |
80 |
81 |
82 | )}
83 |
88 |
93 |
94 |
95 |
96 | {children}
97 |
98 | )
99 | }
100 |
101 | export default Meta
102 |
--------------------------------------------------------------------------------
/components/nav.js:
--------------------------------------------------------------------------------
1 | import { Flex, Heading, Image, Box } from 'theme-ui'
2 | import { motion, useViewportScroll, useAnimation } from 'framer-motion'
3 | import { useEffect } from 'react'
4 | import Link from 'next/link'
5 | import { registrationState, closed } from '../lib/waitlist'
6 |
7 | export const Nav = () => {
8 | const { scrollYProgress } = useViewportScroll()
9 | const controls = useAnimation()
10 | useEffect(
11 | () =>
12 | scrollYProgress.onChange(latest => {
13 | if (latest > 0.1) {
14 | controls.start({
15 | opacity: 1,
16 | transition: { duration: 0.5 },
17 | })
18 | }
19 | if (latest == 0) {
20 | controls.start({
21 | opacity: 0,
22 | transition: { duration: 0.5 },
23 | })
24 | }
25 | }),
26 | [],
27 | )
28 | return (
29 |
49 |
62 |
63 |
68 |
69 | ASSEMBLE
70 |
71 |
72 |
80 | The Hackathon
81 |
82 |
83 |
84 |
92 | The Rundown
93 |
94 |
95 |
101 |
111 | {
112 | {
113 | open: 'Register',
114 | waitlist: 'Join the Waitlist',
115 | closed: 'Registration Closed',
116 | }[registrationState]
117 | }
118 |
119 |
120 |
121 | )
122 | }
123 |
--------------------------------------------------------------------------------
/components/noselect.js:
--------------------------------------------------------------------------------
1 | export default {
2 | WebkitTouchCallout: 'none' /* iOS Safari */,
3 | WebkitUserSelect: 'none' /* Safari */,
4 | KhtmlUserSelect: 'none' /* Konqueror HTML */,
5 | MozUserSelect: 'none' /* Old versions of Firefox */,
6 | MsUserSelect: 'none' /* Internet Explorer/Edge */,
7 | userSelect: 'none' /* NonPrefixed version, currently
8 | supported by Chrome, Edge, Opera and Firefox */,
9 | }
10 |
--------------------------------------------------------------------------------
/components/previously.js:
--------------------------------------------------------------------------------
1 | import { Button, Box, Container, Heading, Text } from 'theme-ui'
2 | import React, { useState } from 'react'
3 | import ReactPlayer from 'react-player/youtube'
4 |
5 | const PreviouslySection = () => {
6 | const [video, toggleVideo] = useState('0')
7 | return (
8 |
14 |
34 |
35 |
44 | Curious about what we did last summer? Check out The Hacker Zephyr
45 | story!
46 |
47 |
56 | toggleVideo('1')}
61 | sx={{ lineHeight: '1.3' }}
62 | >
63 | ► {video != '0.1' ? 'Watch The Video' : 'Resume The Video'}
64 |
65 |
66 |
67 |
68 | toggleVideo('0.1')}
70 | sx={{ display: video != '1' ? 'none' : 'default' }}
71 | >
72 | toggleVideo('0')}
78 | config={{
79 | youtube: {
80 | playerVars: {
81 | showinfo: 1,
82 | autoplay: 0,
83 | modestbranding: 0,
84 | rel: 0,
85 | controls: 1,
86 | },
87 | },
88 | }}
89 | />
90 |
91 |
92 | )
93 | }
94 |
95 | export default PreviouslySection
96 |
--------------------------------------------------------------------------------
/components/project.js:
--------------------------------------------------------------------------------
1 | import { Container, Grid, Text, Box, Heading, Button } from 'theme-ui'
2 | import NextImage from 'next/image'
3 | import ImgFlagship1 from '../public/flagship.jpg'
4 | import ImgFlagship2 from '../public/flagship2.jpg'
5 | import { useState } from 'react'
6 |
7 | const projectData = [
8 | // Example:
9 | // {
10 | // src: 'image src',
11 | // alt: 'image alt text',
12 | // desc: 'text description',
13 | // }
14 | {
15 | src: 'https://cloud-qcrf01idm-hack-club-bot.vercel.app/0-45017250971189591042019-10-20_14.27.38.gif',
16 | alt: 'Created by @quackduck.',
17 | desc: 'What if you made a search engine?',
18 | },
19 | {
20 | src: 'https://cloud-qcrf01idm-hack-club-bot.vercel.app/0-45017250971189591042019-10-20_14.27.38.gif',
21 | alt: 'Created by @zachlatta.',
22 | desc: 'What if you made compiling a fatal error more fatal?',
23 | },
24 | {
25 | src: 'https://cloud-j1v4vj6pn-hack-club-bot.vercel.app/0asdjkhasjkd.png',
26 | alt: 'Created by @aidenybai.',
27 | desc: 'What if you made a camera with a middle finger trigger?',
28 | },
29 | ]
30 |
31 | const ProjectCopy = ({ handleClick, desc }) => (
32 |
46 |
47 | We'll be building all weekend, so...
48 |
49 |
59 | {desc}
60 |
61 |
65 | Get another idea!
66 |
67 |
68 |
69 | )
70 |
71 | const ProjectImage = ({ src, alt, desc }) => (
72 |
82 |
95 | {alt}
96 |
97 |
98 | )
99 |
100 | const ProjectSection = () => {
101 | const [index, setIndex] = useState(0)
102 |
103 | const handleClick = () => {
104 | let updatedIndex = ++index % projectData.length
105 | setIndex(updatedIndex)
106 | }
107 |
108 | return (
109 |
117 |
118 |
119 |
123 |
128 |
129 |
130 |
131 | )
132 | }
133 |
134 | export default ProjectSection
135 |
--------------------------------------------------------------------------------
/components/ref.js:
--------------------------------------------------------------------------------
1 | import Announcement from './announcement'
2 | import { motion, useViewportScroll, useAnimation } from 'framer-motion'
3 | import { useEffect, useState } from 'react'
4 | /** @jsxImportSource theme-ui */
5 |
6 | export const Ref = props => {
7 | const [ref, setRef] = useState('')
8 | const [refCheck, setrefCheck] = useState(false)
9 |
10 | useEffect(() => {
11 | if (typeof window !== 'undefined') {
12 | const queryURL = window.location.search
13 | const urlParams = new URLSearchParams(queryURL)
14 | setRef((ref = urlParams.get('ref')))
15 | }
16 |
17 | if (ref !== null) {
18 | setrefCheck(true)
19 | }
20 |
21 | switch (ref) {
22 | case 'codeday':
23 | setRef('CodeDay')
24 | break
25 | case 'superposition':
26 | setRef('Superposition')
27 | break
28 | case 'kwk':
29 | serRef((ref = 'Kode With Klossy'))
30 | break
31 |
32 | case 'techtogether':
33 | serRef((ref = 'TechTogether'))
34 | break
35 | }
36 |
37 | console.log(ref)
38 | })
39 |
40 | const { scrollYProgress } = useViewportScroll()
41 | const control = useAnimation()
42 |
43 | useEffect(
44 | () =>
45 | scrollYProgress.onChange(latest => {
46 | if (latest <= 0.18) {
47 | control.start({
48 | opacity: 1,
49 | transition: { duration: 0.7 },
50 | })
51 | }
52 | if (latest > 0.18) {
53 | control.start({
54 | opacity: 0,
55 | transition: { duration: 0.7 },
56 | })
57 | }
58 | }),
59 | [],
60 | )
61 |
62 | return (
63 | <>
64 | {refCheck ? (
65 |
66 |
73 |
74 | ) : (
75 | // not super sure why but if motion.div is not called the whole thing turns wack
79 | )}
80 | <>>
81 | >
82 | )
83 | }
84 |
--------------------------------------------------------------------------------
/components/registration.js:
--------------------------------------------------------------------------------
1 | import { Heading } from 'theme-ui'
2 | import { useState, useEffect } from 'react'
3 | import noselect from './noselect.js'
4 |
5 | const wait = ms => new Promise(resolve => setTimeout(() => resolve(), ms))
6 |
7 | export const registrants = (() => {
8 | let output = []
9 | for (let i = 0; i < 30; i++) {
10 | output.push('https://get-a-dino.hackclub.dev/dino.png?' + i)
11 | }
12 | return output
13 | })()
14 |
15 | export default function Registration() {
16 | let [backgroundImages, setBackgroundImages] = useState([
17 | 'https://get-a-dino.hackclub.dev/dino.png',
18 | ])
19 | let [floatingDinos, setFloatingDinos] = useState([])
20 |
21 | useEffect(() => {
22 | ;(async () => {
23 | setFloatingDinos(
24 | registrants.map((registrant, i) => ({
25 | src: registrant,
26 | x: ((i % 6) / 6) * 90 + 12.5,
27 | y: (Math.floor(i / 6) / 5) * 90 + 15,
28 | })),
29 | )
30 | const registrationAudio = new Audio('/registration.mp3')
31 | registrationAudio.currentTime = 12.85
32 | registrationAudio.play()
33 | for (let i = 0; i < 20; i++) {
34 | await wait(1000 * 0.85 ** (i + 1))
35 | console.log([...backgroundImages, registrants[i]])
36 | setBackgroundImages([...backgroundImages, registrants[i]])
37 | }
38 | await wait(40)
39 | setBackgroundImages([])
40 | })()
41 | }, [])
42 |
43 | return (
44 |
55 | {backgroundImages.length ? (
56 |
72 | ) : (
73 |
74 |
75 | {floatingDinos.map(dino => {
76 | return (
77 |
93 | )
94 | })}
95 |
96 |
106 |
116 |
124 | Dinos,
125 |
126 |
141 | Assemble!
142 |
143 |
144 |
145 |
146 | )}
147 |
148 | )
149 | }
150 |
151 | export const cache = async srcArray => {
152 | await Promise.all(
153 | srcArray.map(src => {
154 | return new Promise((resolve, reject) => {
155 | const img = new Image()
156 | console.log(img)
157 |
158 | img.src = src
159 | img.onload = resolve
160 | img.onerror = reject
161 | })
162 | }),
163 | )
164 | }
165 |
--------------------------------------------------------------------------------
/components/rundown.js:
--------------------------------------------------------------------------------
1 | import { Container, Grid, Box, Heading, Text } from 'theme-ui'
2 | import Icon from '@hackclub/icons'
3 | import ImgFlagship1 from '../public/flagship.jpg'
4 | import ImgFlagship2 from '../public/flagship2.jpg'
5 | import NextImage from 'next/image'
6 | import ComicImage from './comic-image'
7 | import { registrationState, closed } from '../lib/waitlist'
8 |
9 | const Card = ({ header = 'header', description = 'description' }) => (
10 |
21 | {header} {description}
22 |
23 | )
24 |
25 | export const Rundown = () => (
26 |
27 |
33 |
34 |
47 | The Rundown & Registration
48 |
49 |
50 |
55 |
69 |
70 | Venue: Figma HQ
71 |
72 | 760 Market St.
73 |
74 | San Francisco, California 94102
75 |
76 |
82 |
87 |
93 |
99 |
100 |
101 |
102 |
111 |
112 |
113 |
120 |
126 |
134 |
135 |
136 |
137 |
138 |
139 | )
140 |
141 | export const WideRegisterButton = () => (
142 |
170 |
171 | {
172 | {
173 | open: 'REGISTER',
174 | closed: 'REGISTRATION CLOSED',
175 | waitlist: 'JOIN THE WAITLIST',
176 | }[registrationState]
177 | }
178 |
179 | {!closed ? (
180 |
187 |
188 |
189 | ) : null}
190 |
191 |
203 | Why a waitlist? Unfortunately, we are overbooked at the moment. {' '}
204 | However, we expect places to open up and will be offering these places to those on the waitlist.
205 |
206 |
207 | )
208 |
--------------------------------------------------------------------------------
/components/second-letter.mdx:
--------------------------------------------------------------------------------
1 | import { Box } from 'theme-ui'
2 |
3 |
4 | We're starting in San Francisco and we invite you to join us. Not through Zoom,
5 | Discord or Devpost, but IRL in the heart of the city for a hackathon of the
6 | ages. You’ll explore the Bay Area during your free time, hack with
7 | co-conspirators, solve a mystery at midnight, and experience the energy of being
8 | in-person again.
9 |
10 | We can't do this alone. After Assemble, we'll open source the entire event,
11 | launch a guide to creating a hackathon and work with you to start your own
12 | hackathon. Together, we'll kick start a high school hackathon renaissance.
13 |
14 |
15 |
--------------------------------------------------------------------------------
/components/signup.js:
--------------------------------------------------------------------------------
1 | const SignupSection = () => (
2 |
8 |
9 |
10 |
11 |
12 | )
13 |
14 | export default SignUpSection
15 |
--------------------------------------------------------------------------------
/lib/theme.js:
--------------------------------------------------------------------------------
1 | export const colors = {
2 | pink: '#c23371',
3 | red: '#C0362C',
4 | yellow: '#b1bb2b',
5 | green: '#1c7b52',
6 | blue: '#1a3f71',
7 | purple: '#6e1968',
8 | orange: '#ba7c2b',
9 | darker: '#0b1a2e',
10 | dark: '#050b14',
11 | darkless: '#02060a',
12 |
13 | black: '#0b1a2e',
14 | steel: '#273444',
15 | slate: '#3c4858',
16 | muted: '#050b14',
17 | smoke: '#e0e6ed',
18 | snow: '#f9fafc',
19 | white: '#FFF8F2',
20 |
21 | // twitter: '#1da1f2',
22 | // facebook: '#3b5998',
23 | // instagram: '#e1306c',
24 | }
25 |
26 | export const fonts = `ui-rounded, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Helvetica, sans-serif`
27 |
28 | const theme = {
29 | breakpoints: [32, 48, 64, 96, 128].map(w => `${w}em`),
30 | space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
31 | fontSizes: [12, 16, 20, 24, 32, 48, 64, 96, 128, 160, 192],
32 | config: {
33 | initialColorModeName: 'light',
34 | useColorSchemeMediaQuery: true,
35 | },
36 | colors: {
37 | ...colors,
38 | primary: colors.blue,
39 | accent: colors.yellow,
40 | inverted: colors.white,
41 | text: colors.black,
42 | background: colors.white,
43 | elevated: colors.white,
44 | sheet: colors.snow,
45 | sunken: colors.smoke,
46 | border: colors.smoke,
47 | placeholder: colors.muted,
48 | secondary: colors.slate,
49 | muted: colors.muted,
50 | },
51 | fonts: {
52 | monospace: 'ui-monospace, "Roboto Mono", Menlo, Consolas, monospace',
53 | heading: `ui-rounded,Nunito,${fonts}`,
54 | body: `${fonts}`,
55 | },
56 | lineHeights: {
57 | limit: 0.875,
58 | title: 1,
59 | heading: 1.125,
60 | subheading: 1.25,
61 | caption: 1.375,
62 | body: 1.5,
63 | },
64 | fontWeights: {
65 | body: 300,
66 | bold: 700,
67 | heading: 800,
68 | },
69 | letterSpacings: {
70 | title: '-0.009em',
71 | headline: '0.009em',
72 | },
73 | sizes: {
74 | widePlus: 2048,
75 | wide: 1536,
76 | layoutPlus: 1200,
77 | layout: 1024,
78 | copyUltra: 980,
79 | copyPlus: 768,
80 | copy: 680,
81 | narrowPlus: 600,
82 | narrow: 512,
83 | },
84 | radii: {
85 | small: 3,
86 | default: 6,
87 | extra: 9,
88 | ultra: 18,
89 | circle: 99999,
90 | },
91 | shadows: {
92 | text: '0 1px 2px rgba(0, 0, 0, 0.25), 0 2px 4px rgba(0, 0, 0, 0.125)',
93 | small: '0 1px 2px rgba(0, 0, 0, 0.0625), 0 2px 4px rgba(0, 0, 0, 0.0625)',
94 | card: '0 4px 8px rgba(0, 0, 0, 0.125)',
95 | elevated:
96 | '0 1px 2px rgba(0, 0, 0, 0.0625), 0 8px 12px rgba(0, 0, 0, 0.125)',
97 | },
98 | text: {
99 | heading: {
100 | fontFamily: 'heading',
101 | fontWeight: 'heading',
102 | lineHeight: 'heading',
103 | letterSpacing: 'headline',
104 | mt: 0,
105 | mb: 0,
106 | },
107 | ultratitle: {
108 | fontSize: [5, 6, 7],
109 | lineHeight: 'title',
110 | fontWeight: 'heading',
111 | letterSpacing: 'title',
112 | },
113 | title: {
114 | variant: 'text.heading',
115 | fontSize: [5, 6],
116 | letterSpacing: 'title',
117 | lineHeight: 'title',
118 | },
119 | subtitle: {
120 | mt: 1,
121 | mb: 4,
122 | color: 'secondary',
123 | fontSize: [2, 3],
124 | fontFamily: 'body',
125 | fontWeight: 'body',
126 | letterSpacing: 'headline',
127 | lineHeight: 'subheading',
128 | },
129 | headline: {
130 | fontFamily: 'heading',
131 | fontWeight: 'heading',
132 | letterSpacing: 'headline',
133 | lineHeight: 'heading',
134 | fontSize: 4,
135 | mt: 3,
136 | mb: 3,
137 | },
138 | subheadline: {
139 | fontFamily: 'heading',
140 | lineHeight: 'subheading',
141 | fontSize: 3,
142 | mt: 0,
143 | mb: 3,
144 | },
145 | eyebrow: {
146 | color: 'muted',
147 | fontSize: [3, 4],
148 | fontWeight: 'bold',
149 | letterSpacing: 'headline',
150 | lineHeight: 'subheading',
151 | textTransform: 'uppercase',
152 | mt: 0,
153 | mb: 2,
154 | },
155 | lead: {
156 | fontSize: [2, 3],
157 | my: [2, 3],
158 | },
159 | caption: {
160 | color: 'muted',
161 | fontSize: 1,
162 | letterSpacing: 'headline',
163 | lineHeight: 'caption',
164 | },
165 | },
166 | alerts: {
167 | primary: {
168 | borderRadius: 'default',
169 | bg: 'yellow',
170 | color: 'background',
171 | fontWeight: 'body',
172 | lineHeight: 'heading',
173 | },
174 | },
175 | badges: {
176 | pill: {
177 | borderRadius: 'circle',
178 | px: 3,
179 | py: 1,
180 | },
181 | outline: {
182 | borderRadius: 'circle',
183 | px: 3,
184 | py: 1,
185 | bg: 'transparent',
186 | borderStyle: 'solid',
187 | borderWidth: [3, 5],
188 | borderColor: 'currentColor',
189 | },
190 | },
191 | buttons: {
192 | primary: {
193 | py: 2,
194 | px: 3,
195 | textDecoration: 'none',
196 | display: 'inline-block',
197 | color: 'white',
198 | cursor: 'pointer',
199 | fontFamily: 'heading',
200 | fontWeight: 'bold',
201 | borderRadius: 'default',
202 | textShadow: 'none',
203 | boxShadow: 'card',
204 | WebkitTapHighlightColor: 'transparent',
205 | transition: 'transform .125s ease-in-out, box-shadow .125s ease-in-out',
206 | ':focus,:hover': {
207 | boxShadow: 'elevated',
208 | transform: 'scale(1.0625)',
209 | },
210 | svg: { ml: -1, mr: 2, verticalAlign: 'middle' },
211 | },
212 | lg: {
213 | variant: 'buttons.primary',
214 | fontSize: 3,
215 | lineHeight: 'title',
216 | px: 4,
217 | py: 3,
218 | },
219 | outline: {
220 | variant: 'buttons.primary',
221 | bg: 'transparent',
222 | color: 'primary',
223 | border: '3px solid currentColor',
224 | },
225 | outlineLg: {
226 | variant: 'buttons.primary',
227 | bg: 'transparent',
228 | color: 'primary',
229 | border: '2px solid currentColor',
230 | lineHeight: 'title',
231 | fontSize: 3,
232 | px: 4,
233 | py: 3,
234 | },
235 | },
236 | cards: {
237 | primary: {
238 | bg: 'elevated',
239 | color: 'text',
240 | p: [3, 4],
241 | borderRadius: 'extra',
242 | boxShadow: 'card',
243 | overflow: 'hidden',
244 | },
245 | sunken: {
246 | bg: 'sunken',
247 | p: [3, 4],
248 | borderRadius: 'extra',
249 | 'th, td': { borderColor: 'muted' },
250 | },
251 | interactive: {
252 | variant: 'cards.primary',
253 | textDecoration: 'none',
254 | WebkitTapHighlightColor: 'transparent',
255 | transition: 'transform .125s ease-in-out, box-shadow .125s ease-in-out',
256 | ':hover,:focus': {
257 | transform: 'scale(1.0625)',
258 | boxShadow: 'elevated',
259 | },
260 | },
261 | },
262 | forms: {
263 | input: {
264 | color: 'text',
265 | fontFamily: 'inherit',
266 | borderRadius: 'base',
267 | border: 0,
268 | '::-webkit-input-placeholder': { color: 'placeholder' },
269 | '::-moz-placeholder': { color: 'placeholder' },
270 | ':-ms-input-placeholder': { color: 'placeholder' },
271 | '&[type="search"]::-webkit-search-decoration': { display: 'none' },
272 | },
273 | textarea: { variant: 'forms.input' },
274 | select: { variant: 'forms.input' },
275 | label: {
276 | color: 'text',
277 | display: 'flex',
278 | flexDirection: 'column',
279 | textAlign: 'left',
280 | lineHeight: 'caption',
281 | fontSize: 2,
282 | },
283 | },
284 | layout: {
285 | container: {
286 | maxWidth: ['layout', null, 'layoutPlus'],
287 | width: '100%',
288 | mx: 'auto',
289 | px: 3,
290 | },
291 | wide: {
292 | variant: 'layout.container',
293 | maxWidth: ['layout', null, 'wide'],
294 | },
295 | copy: {
296 | variant: 'layout.container',
297 | maxWidth: ['copy', null, 'copyPlus'],
298 | },
299 | narrow: {
300 | variant: 'layout.container',
301 | maxWidth: ['narrow', null, 'narrowPlus'],
302 | },
303 | },
304 | styles: {
305 | root: {
306 | fontFamily: 'body',
307 | lineHeight: 'body',
308 | fontWeight: 'body',
309 | color: 'text',
310 | margin: 0,
311 | overflowX: 'hidden',
312 | minHeight: '100vh',
313 | textRendering: 'optimizeLegibility',
314 | WebkitFontSmoothing: 'antialiased',
315 | MozOsxFontSmoothing: 'grayscale',
316 | },
317 | h1: {
318 | variant: 'text.heading',
319 | fontSize: 5,
320 | },
321 | h2: {
322 | variant: 'text.heading',
323 | fontSize: 4,
324 | },
325 | h3: {
326 | variant: 'text.eyebrow',
327 | fontSize: 3,
328 | mb: 0,
329 | },
330 | h4: {
331 | variant: 'text.heading',
332 | fontSize: 2,
333 | },
334 | h5: {
335 | variant: 'text.heading',
336 | fontSize: 1,
337 | },
338 | h6: {
339 | variant: 'text.heading',
340 | fontSize: 0,
341 | },
342 | p: {
343 | color: 'text',
344 | fontWeight: 'body',
345 | lineHeight: 'body',
346 | my: 3,
347 | },
348 | img: {
349 | maxWidth: '100%',
350 | },
351 | hr: {
352 | border: '2px solid',
353 | borderColor: 'accent',
354 | borderRadius: 2,
355 | maxWidth: 256,
356 | mx: 'auto',
357 | my: 4,
358 | },
359 | a: {
360 | color: 'primary',
361 | textDecoration: 'inherit',
362 | },
363 | pre: {
364 | fontFamily: 'monospace',
365 | fontSize: 1,
366 | p: 3,
367 | color: 'text',
368 | bg: 'sunken',
369 | overflow: 'auto',
370 | borderRadius: 'default',
371 | },
372 | code: {
373 | fontFamily: 'monospace',
374 | fontSize: 'inherit',
375 | color: 'accent',
376 | bg: 'sunken',
377 | borderRadius: 'small',
378 | mx: 1,
379 | px: 1,
380 | },
381 | li: {
382 | my: 2,
383 | },
384 | table: {
385 | width: '100%',
386 | my: 4,
387 | borderCollapse: 'separate',
388 | borderSpacing: 0,
389 | 'th,td': {
390 | textAlign: 'left',
391 | py: '4px',
392 | pr: '4px',
393 | pl: 0,
394 | borderColor: 'border',
395 | borderBottomStyle: 'solid',
396 | },
397 | },
398 | th: {
399 | verticalAlign: 'bottom',
400 | borderBottomWidth: '1px',
401 | },
402 | td: {
403 | verticalAlign: 'top',
404 | borderBottomWidth: '0.5px',
405 | },
406 | },
407 | util: {
408 | motion: '@media (prefers-reduced-motion: no-preference)',
409 | reduceMotion: '@media (prefers-reduced-motion: reduce)',
410 | reduceTransparency: '@media (prefers-reduced-transparency: reduce)',
411 | supportsClipText: '@supports (-webkit-background-clip: text)',
412 | supportsBackdrop:
413 | '@supports (-webkit-backdrop-filter: none) or (backdrop-filter: none)',
414 | },
415 | }
416 |
417 | theme.util.cx = c => theme.colors[c] || c
418 | theme.util.gx = (from, to) => `radial-gradient(
419 | ellipse farthest-corner at top left,
420 | ${theme.util.cx(from)},
421 | ${theme.util.cx(to)}
422 | )`
423 | theme.util.gxText = (from, to) => ({
424 | color: theme.util.cx(to),
425 | [theme.util.supportsClipText]: {
426 | backgroundImage: theme.util.gx(from, to),
427 | backgroundRepeat: 'no-repeat',
428 | WebkitBackgroundClip: 'text',
429 | WebkitTextFillColor: 'transparent',
430 | },
431 | })
432 |
433 | theme.cards.translucent = {
434 | // variant: 'cards.primary',
435 | backgroundColor: 'rgba(255, 255, 255, 0.98)',
436 | color: 'text',
437 | boxShadow: 'none',
438 | [theme.util.supportsBackdrop]: {
439 | backgroundColor: 'rgba(255, 255, 255, 0.75)',
440 | backdropFilter: 'saturate(180%) blur(20px)',
441 | WebkitBackdropFilter: 'saturate(180%) blur(20px)',
442 | },
443 | [theme.util.reduceTransparency]: {
444 | backdropFilter: 'none',
445 | WebkitBackdropFilter: 'none',
446 | },
447 | }
448 | theme.cards.translucentDark = {
449 | // variant: 'cards.primary',
450 | backgroundColor: 'rgba(0, 0, 0, 0.875)',
451 | color: 'white',
452 | boxShadow: 'none',
453 | [theme.util.supportsBackdrop]: {
454 | backgroundColor: 'rgba(0, 0, 0, 0.625)',
455 | backdropFilter: 'saturate(180%) blur(16px)',
456 | WebkitBackdropFilter: 'saturate(180%) blur(16px)',
457 | },
458 | [theme.util.reduceTransparency]: {
459 | backdropFilter: 'none',
460 | WebkitBackdropFilter: 'none',
461 | },
462 | }
463 |
464 | export default theme
465 |
--------------------------------------------------------------------------------
/lib/waitlist.js:
--------------------------------------------------------------------------------
1 | export const registrationState = 'waitlist'
2 |
3 | export const open = registrationState === 'open'
4 | export const waitlist = registrationState === 'waitlist'
5 | export const closed = registrationState === 'closed'
6 |
7 | export default registrationState
8 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | const { redirect } = require('next/dist/server/api-utils')
2 |
3 | const withMDX = require('@next/mdx')({ extension: /\.mdx?$/ })
4 | module.exports = withMDX({
5 | pageExtensions: ['js', 'mdx'],
6 | async redirects() {
7 | return [
8 | {
9 | source: '/',
10 | permanent: false,
11 | destination: 'https://github.com/hackclub/assemble',
12 | },
13 | {
14 | source: '/register',
15 | permanent: true,
16 | destination: 'https://register.assemble.hackclub.com',
17 | },
18 | {
19 | source: '/email',
20 | permanent: true,
21 | destination: 'mailto:assemble@hackclub.com',
22 | },
23 | {
24 | source: '/photos',
25 | permanent: false,
26 | destination: 'https://hack.af/assemble-photos',
27 | },
28 | ]
29 | },
30 | async headers() {
31 | return [
32 | {
33 | source: '/hackers-assemble.png',
34 | headers: [
35 | {
36 | key: 'Cache-Control',
37 | value: 'public, max-age=3600, stale-while-revalidate=3600',
38 | },
39 | ],
40 | },
41 | ]
42 | },
43 | })
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@lachlanjc/theme-starter",
3 | "version": "0.0.1",
4 | "author": "Lachlan Campbell (https://lachlanjc.com) ",
5 | "license": "MIT",
6 | "private": true,
7 | "scripts": {
8 | "dev": "next",
9 | "build": "next build",
10 | "start": "next start",
11 | "lint": "next lint"
12 | },
13 | "dependencies": {
14 | "@emotion/react": "^11.9.0",
15 | "@emotion/styled": "^11.8.1",
16 | "@hackclub/design-system": "^0.0.1-18",
17 | "@hackclub/icons": "^0.0.9",
18 | "@mattjennings/react-modal": "^1.0.3",
19 | "@mattjennings/react-modal-stack": "^1.0.4",
20 | "@mdx-js/loader": "^1.6.22",
21 | "@mdx-js/react": "^1.6.22",
22 | "@next/mdx": "^12.1.0",
23 | "framer-motion": "3.10.6",
24 | "next": "^12.1.0",
25 | "react": "^17.0.2",
26 | "react-dom": "^17.0.2",
27 | "react-player": "^2.10.1",
28 | "sharp": "^0.30.6",
29 | "styled-components": "^5.3.5",
30 | "theme-ui": "^0.14.5"
31 | },
32 | "devDependencies": {
33 | "eslint": "8.10.0",
34 | "eslint-config-next": "12.1.0"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import { withModalTheme } from '@mattjennings/react-modal'
3 | import Meta from '../components/meta'
4 | import theme from '../lib/theme'
5 | import { ThemeProvider } from 'theme-ui'
6 | import '../public/global.css'
7 | import { useEatSterEgg } from '../components/eat-ster-egg'
8 |
9 | const App = ({ Component, pageProps }) => {
10 | useEatSterEgg()
11 |
12 | return (
13 |
14 |
15 |
16 |
19 |
20 | )
21 | }
22 |
23 | export default App
24 |
--------------------------------------------------------------------------------
/pages/_document.js:
--------------------------------------------------------------------------------
1 | import { Html, Head, Main, NextScript } from 'next/document'
2 | import { InitializeColorMode } from 'theme-ui'
3 |
4 | export default function Document() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/pages/api/validation.js:
--------------------------------------------------------------------------------
1 | export default function validation(req, res) {
2 | function _0x40bf() {
3 | var _0xf16ef4 = [
4 | 'assemble',
5 | 'body',
6 | '3751iVeySi',
7 | '2588TSICCg',
8 | '142179ZvgMJN',
9 | '32oaFnZD',
10 | '91RNlnIc',
11 | '256644zHPGdd',
12 | 'input',
13 | 'endsWith',
14 | '3030YWxRoD',
15 | '12BFYYxF',
16 | '1708884weTDpb',
17 | '12zrLNBY',
18 | '9180Gzncwz',
19 | '65579JTDDJo',
20 | 'json',
21 | '562254cfiYPq',
22 | ]
23 | _0x40bf = function () {
24 | return _0xf16ef4
25 | }
26 | return _0x40bf()
27 | }
28 | function _0x2fd7(_0x9745d5, _0xee3d8) {
29 | var _0x40bf81 = _0x40bf()
30 | return (
31 | (_0x2fd7 = function (_0x2fd7ba, _0x23d10f) {
32 | _0x2fd7ba = _0x2fd7ba - 0x131
33 | var _0x4a87eb = _0x40bf81[_0x2fd7ba]
34 | return _0x4a87eb
35 | }),
36 | _0x2fd7(_0x9745d5, _0xee3d8)
37 | )
38 | }
39 | var _0x3c9b02 = _0x2fd7
40 | ;(function (_0x496982, _0x58d91e) {
41 | var _0x12edd6 = _0x2fd7,
42 | _0x164947 = _0x496982()
43 | while (!![]) {
44 | try {
45 | var _0x116055 =
46 | (parseInt(_0x12edd6(0x132)) / 0x1) *
47 | (-parseInt(_0x12edd6(0x140)) / 0x2) +
48 | -parseInt(_0x12edd6(0x139)) / 0x3 +
49 | (-parseInt(_0x12edd6(0x138)) / 0x4) *
50 | (parseInt(_0x12edd6(0x13f)) / 0x5) +
51 | (parseInt(_0x12edd6(0x142)) / 0x6) *
52 | (-parseInt(_0x12edd6(0x134)) / 0x7) +
53 | (parseInt(_0x12edd6(0x13a)) / 0x8) *
54 | (-parseInt(_0x12edd6(0x13c)) / 0x9) +
55 | (-parseInt(_0x12edd6(0x131)) / 0xa) *
56 | (-parseInt(_0x12edd6(0x137)) / 0xb) +
57 | (parseInt(_0x12edd6(0x141)) / 0xc) *
58 | (parseInt(_0x12edd6(0x13b)) / 0xd)
59 | if (_0x116055 === _0x58d91e) break
60 | else _0x164947['push'](_0x164947['shift']())
61 | } catch (_0x249f17) {
62 | _0x164947['push'](_0x164947['shift']())
63 | }
64 | }
65 | })(_0x40bf, 0x315f6),
66 | res[_0x3c9b02(0x133)]({
67 | success: req[_0x3c9b02(0x136)][_0x3c9b02(0x13d)][_0x3c9b02(0x13e)](
68 | _0x3c9b02(0x135),
69 | ),
70 | })
71 | }
72 |
--------------------------------------------------------------------------------
/pages/dinos.js:
--------------------------------------------------------------------------------
1 | import AudioCheck from '../components/audio-check'
2 | import { useEffect } from 'react'
3 | import Registration, { cache, registrants } from '../components/registration'
4 |
5 | export default () => {
6 | useEffect(() => {
7 | setTimeout(() => {
8 | cache(registrants);
9 | }, 1000);
10 | }, []);
11 |
12 | return (
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import { Hero } from "../components/hero"
2 | import HeaderSection from "../components/index/header-section"
3 | import { Nav } from "../components/nav"
4 |
5 | export default function Index() {
6 | return (
7 | <>
8 |
9 |
10 |
11 | {/* Section about documentation/open source */}
12 | {/* Section about projects */}
13 | {/* Section about old site */}
14 |
15 | >
16 | )
17 | }
--------------------------------------------------------------------------------
/pages/launch.js:
--------------------------------------------------------------------------------
1 | import { Box } from 'theme-ui'
2 | import DinoEasterEgg from '../components/dino-easter-egg'
3 | import Footer from '../components/footer'
4 | import Glossary from '../components/glossary'
5 | import PreviouslySection from '../components/previously'
6 | import ProjectSection from '../components/project'
7 | import { Nav } from '../components/nav'
8 | import { Letter } from '../components/letter'
9 | import { Rundown } from '../components/rundown'
10 | import { Features } from '../components/features'
11 | import { BetaWelcome } from '../components/beta-welcome'
12 | import { Ref } from '../components/ref'
13 | import { useEffect, useState } from 'react'
14 | import Registration, { cache, registrants } from '../components/registration'
15 |
16 | export default function Launch() {
17 | const [showRegistration, setShowRegistration] = useState(false)
18 |
19 | useEffect(() => {
20 | console.log(` █████╗ ███████╗███████╗███████╗███╗ ███╗██████╗ ██╗ ███████╗
21 | ██╔══██╗██╔════╝██╔════╝██╔════╝████╗ ████║██╔══██╗██║ ██╔════╝
22 | ███████║███████╗███████╗█████╗ ██╔████╔██║██████╔╝██║ █████╗
23 | ██╔══██║╚════██║╚════██║██╔══╝ ██║╚██╔╝██║██╔══██╗██║ ██╔══╝
24 | ██║ ██║███████║███████║███████╗██║ ╚═╝ ██║██████╔╝███████╗███████╗
25 | ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝
26 |
27 | Hey hacker! Register for Assemble at https://assemble.hackclub.com/register. We hope to see you there!`)
28 | if (!window.enableValidation) {
29 | setTimeout(() => {
30 | cache(registrants)
31 | }, 8000)
32 | let input = ``
33 | window.enableValidation = true
34 | window.onkeydown = async event => {
35 | input += event.key.toLowerCase()
36 | if (!input.endsWith('e')) return
37 |
38 | const { success } = await fetch('/api/validation', {
39 | method: 'POST',
40 | headers: { 'Content-Type': 'application/json' },
41 | body: JSON.stringify({ input }),
42 | }).then(res => res.json())
43 |
44 | if (success) setShowRegistration(true)
45 | }
46 | }
47 | // Credit to https://workshops.hackclub.com/konami_code/ for the logic of the konami code.
48 | const keys = []
49 | const secretCode = [
50 | 'ArrowUp',
51 | 'ArrowUp',
52 | 'ArrowDown',
53 | 'ArrowDown',
54 | 'ArrowLeft',
55 | 'ArrowRight',
56 | 'ArrowLeft',
57 | 'ArrowRight',
58 | 'b',
59 | 'a',
60 | 'Enter',
61 | ]
62 | window.addEventListener('keyup', e => {
63 | keys.push(e.key)
64 | if (keys.length > secretCode.length) {
65 | keys.shift()
66 | }
67 | if (JSON.stringify(keys) === JSON.stringify(secretCode)) {
68 | // Credit to https://github.com/sc420/jellify-ur-website for designing this amazing jellifing bookmarklet!
69 |
70 | const urls = [
71 | // Dependencies should be loaded first
72 | 'https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js',
73 | 'https://cdn.jsdelivr.net/npm/matter-js@0.17.1/build/matter.min.js',
74 | // Main script is loaded last
75 | 'https://sc420.github.io/jellify-ur-website/js/jellify.js',
76 | ]
77 | urls.forEach(url => {
78 | const head = document.getElementsByTagName('head')[0]
79 | const script = document.createElement('script')
80 | script.src = url
81 | head.appendChild(script)
82 | })
83 | }
84 | })
85 | }, [])
86 | return (
87 | <>
88 |
89 |
90 | {true && }
91 | {/* */}
92 |
93 | {false && }
94 |
95 | {true && }
96 | {true && }
97 | {true && }
98 |
99 | {showRegistration && }
100 | >
101 | )
102 | }
103 |
--------------------------------------------------------------------------------
/pages/styles.module.css:
--------------------------------------------------------------------------------
1 | @keyframes flicker {
2 | 0% {
3 | opacity: 0.27861;
4 | }
5 | 5% {
6 | opacity: 0.34769;
7 | }
8 | 10% {
9 | opacity: 0.23604;
10 | }
11 | 15% {
12 | opacity: 0.90626;
13 | }
14 | 20% {
15 | opacity: 0.18128;
16 | }
17 | 25% {
18 | opacity: 0.83891;
19 | }
20 | 30% {
21 | opacity: 0.65583;
22 | }
23 | 35% {
24 | opacity: 0.67807;
25 | }
26 | 40% {
27 | opacity: 0.26559;
28 | }
29 | 45% {
30 | opacity: 0.84693;
31 | }
32 | 50% {
33 | opacity: 0.96019;
34 | }
35 | 55% {
36 | opacity: 0.08594;
37 | }
38 | 60% {
39 | opacity: 0.20313;
40 | }
41 | 65% {
42 | opacity: 0.71988;
43 | }
44 | 70% {
45 | opacity: 0.53455;
46 | }
47 | 75% {
48 | opacity: 0.37288;
49 | }
50 | 80% {
51 | opacity: 0.71428;
52 | }
53 | 85% {
54 | opacity: 0.70419;
55 | }
56 | 90% {
57 | opacity: 0.7003;
58 | }
59 | 95% {
60 | opacity: 0.36108;
61 | }
62 | 100% {
63 | opacity: 0.24387;
64 | }
65 | }
66 | @keyframes textShadow {
67 | 0% {
68 | text-shadow: 0.4389924193300864px 0 1px rgba(0, 30, 255, 0.5),
69 | -0.4389924193300864px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
70 | }
71 | 5% {
72 | text-shadow: 2.7928974010788217px 0 1px rgba(0, 30, 255, 0.5),
73 | -2.7928974010788217px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
74 | }
75 | 10% {
76 | text-shadow: 0.02956275843481219px 0 1px rgba(0, 30, 255, 0.5),
77 | -0.02956275843481219px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
78 | }
79 | 15% {
80 | text-shadow: 0.40218538552878136px 0 1px rgba(0, 30, 255, 0.5),
81 | -0.40218538552878136px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
82 | }
83 | 20% {
84 | text-shadow: 3.4794037899852017px 0 1px rgba(0, 30, 255, 0.5),
85 | -3.4794037899852017px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
86 | }
87 | 25% {
88 | text-shadow: 1.6125630401149584px 0 1px rgba(0, 30, 255, 0.5),
89 | -1.6125630401149584px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
90 | }
91 | 30% {
92 | text-shadow: 0.7015590085143956px 0 1px rgba(0, 30, 255, 0.5),
93 | -0.7015590085143956px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
94 | }
95 | 35% {
96 | text-shadow: 3.896914047650351px 0 1px rgba(0, 30, 255, 0.5),
97 | -3.896914047650351px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
98 | }
99 | 40% {
100 | text-shadow: 3.870905614848819px 0 1px rgba(0, 30, 255, 0.5),
101 | -3.870905614848819px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
102 | }
103 | 45% {
104 | text-shadow: 2.231056963361899px 0 1px rgba(0, 30, 255, 0.5),
105 | -2.231056963361899px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
106 | }
107 | 50% {
108 | text-shadow: 0.08084290417898504px 0 1px rgba(0, 30, 255, 0.5),
109 | -0.08084290417898504px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
110 | }
111 | 55% {
112 | text-shadow: 2.3758461067427543px 0 1px rgba(0, 30, 255, 0.5),
113 | -2.3758461067427543px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
114 | }
115 | 60% {
116 | text-shadow: 2.202193051050636px 0 1px rgba(0, 30, 255, 0.5),
117 | -2.202193051050636px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
118 | }
119 | 65% {
120 | text-shadow: 2.8638780614874975px 0 1px rgba(0, 30, 255, 0.5),
121 | -2.8638780614874975px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
122 | }
123 | 70% {
124 | text-shadow: 0.48874025155497314px 0 1px rgba(0, 30, 255, 0.5),
125 | -0.48874025155497314px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
126 | }
127 | 75% {
128 | text-shadow: 1.8948491305757957px 0 1px rgba(0, 30, 255, 0.5),
129 | -1.8948491305757957px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
130 | }
131 | 80% {
132 | text-shadow: 0.0833037308038857px 0 1px rgba(0, 30, 255, 0.5),
133 | -0.0833037308038857px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
134 | }
135 | 85% {
136 | text-shadow: 0.09769827255241735px 0 1px rgba(0, 30, 255, 0.5),
137 | -0.09769827255241735px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
138 | }
139 | 90% {
140 | text-shadow: 3.443339761481782px 0 1px rgba(0, 30, 255, 0.5),
141 | -3.443339761481782px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
142 | }
143 | 95% {
144 | text-shadow: 2.1841838852799786px 0 1px rgba(0, 30, 255, 0.5),
145 | -2.1841838852799786px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
146 | }
147 | 100% {
148 | text-shadow: 2.6208764473832513px 0 1px rgba(0, 30, 255, 0.5),
149 | -2.6208764473832513px 0 1px rgba(255, 0, 80, 0.3), 0 0 3px;
150 | }
151 | }
152 | .crt::after {
153 | content: ' ';
154 | display: block;
155 | position: absolute;
156 | top: 0;
157 | left: 0;
158 | bottom: 0;
159 | right: 0;
160 | background: rgba(18, 16, 16, 0.1);
161 | opacity: 0;
162 | z-index: 2;
163 | pointer-events: none;
164 | animation: flicker 0.15s infinite;
165 | }
166 | .crt::before {
167 | content: ' ';
168 | display: block;
169 | position: absolute;
170 | top: 0;
171 | left: 0;
172 | bottom: 0;
173 | right: 0;
174 | background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%),
175 | linear-gradient(
176 | 90deg,
177 | rgba(255, 0, 0, 0.06),
178 | rgba(0, 255, 0, 0.02),
179 | rgba(0, 0, 255, 0.06)
180 | );
181 | z-index: 2;
182 | background-size: 100% 2px, 3px 100%;
183 | pointer-events: none;
184 | }
185 |
186 | .crt > h2 {
187 | animation: flicker 2s infinite;
188 | }
189 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | singleQuote: true,
3 | trailingComma: 'all',
4 | arrowParens: 'avoid',
5 | printWidth: 80,
6 | semi: false,
7 | tabWidth: 2,
8 | }
9 |
--------------------------------------------------------------------------------
/public/date.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/dinosaur-waving.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/dinosaur-waving.png
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/favicon.png
--------------------------------------------------------------------------------
/public/figmahqbeige.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/figmahqbeige.jpg
--------------------------------------------------------------------------------
/public/flagship.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/flagship.jpg
--------------------------------------------------------------------------------
/public/flagship2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/flagship2.jpg
--------------------------------------------------------------------------------
/public/global.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Luckiest+Guy&display=swap');
2 | @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
3 |
4 | /* Begin Phantom Sans */
5 |
6 | @font-face {
7 | font-family: 'Phantom Sans';
8 | src: url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Regular.woff')
9 | format('woff'),
10 | url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Regular.woff2')
11 | format('woff2');
12 | font-weight: normal;
13 | font-style: normal;
14 | font-display: swap;
15 | }
16 |
17 | @font-face {
18 | font-family: 'Phantom Sans';
19 | src: url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Italic.woff')
20 | format('woff'),
21 | url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Italic.woff2')
22 | format('woff2');
23 | font-weight: normal;
24 | font-style: italic;
25 | font-display: swap;
26 | }
27 |
28 | @font-face {
29 | font-family: 'Phantom Sans';
30 | src: url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Bold.woff')
31 | format('woff'),
32 | url('https://assets.hackclub.com/fonts/Phantom_Sans_0.7/Bold.woff2')
33 | format('woff2');
34 | font-weight: bold;
35 | font-style: normal;
36 | font-display: swap;
37 | }
38 |
39 | /* End Phantom Sans */
40 |
41 | * {
42 | box-sizing: border-box;
43 | }
44 |
45 | b {
46 | font-weight: 700;
47 | }
48 |
49 | body {
50 | background: white;
51 | }
52 |
53 | .comicHeader {
54 | color: #fcd1cf;
55 | font-family: 'Luckiest Guy';
56 | -webkit-font-smoothing: antialiased;
57 | -moz-osx-font-smoothing: grayscale;
58 | transform: translateY(22px);
59 | letter-spacing: 12px;
60 | text-shadow: 0px -2px 0 #212121, 0px -2px 0 #212121, 0px 6px 0 #212121,
61 | 0px 6px 0 #212121, -6px 0px 0 #212121, 6px 0px 0 #212121, -6px 0px 0 #212121,
62 | 6px 0px 0 #212121, -6px -6px 0 #212121, 6px -6px 0 #212121,
63 | -6px 6px 0 #212121, 6px 6px 0 #212121, -6px 18px 0 #212121,
64 | 0px 18px 0 #212121, 6px 18px 0 #212121, 0 19px 1px rgba(0, 0, 0, 0.1),
65 | 0 0 6px rgba(0, 0, 0, 0.1), 0 6px 3px rgba(0, 0, 0, 0.3),
66 | 0 12px 6px rgba(0, 0, 0, 0.2), 0 18px 18px rgba(0, 0, 0, 0.25),
67 | 0 24px 24px rgba(0, 0, 0, 0.2), 0 36px 36px rgba(0, 0, 0, 0.15);
68 | }
69 |
70 | .largeRegisterButton:not(.closed):hover > .externalIcon {
71 | transform: translate(4px, 0px) scale(2);
72 | }
73 |
74 | .largeRegisterButton:not(.closed):hover > .assembleRegisterText {
75 | position: relative;
76 | left: -4px;
77 | top: 0px;
78 | }
79 |
80 | .largeRegisterButton:not(.closed) > .assembleRegisterText {
81 | position: relative;
82 | left: 0px;
83 | top: 0px;
84 | }
85 |
86 | .largeRegisterButton,
87 | .largeRegisterButton * {
88 | transition: 0.2s all;
89 | }
90 |
91 | .navMainLink,
92 | .navMainLink * {
93 | text-decoration: none;
94 | color: white !important;
95 | cursor: pointer;
96 | font-family: 'Space Grotesk' !important;
97 | }
98 |
--------------------------------------------------------------------------------
/public/hackers-assemble.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/hackers-assemble.jpg
--------------------------------------------------------------------------------
/public/hackers-assemble.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/hackers-assemble.png
--------------------------------------------------------------------------------
/public/ingot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/ingot.png
--------------------------------------------------------------------------------
/public/invert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/invert.png
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/logo.png
--------------------------------------------------------------------------------
/public/meta-assemble.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/meta-assemble.png
--------------------------------------------------------------------------------
/public/minimal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/minimal.png
--------------------------------------------------------------------------------
/public/orpheus-pop-closed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/orpheus-pop-closed.png
--------------------------------------------------------------------------------
/public/orpheus-pop-open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/orpheus-pop-open.png
--------------------------------------------------------------------------------
/public/parallax/golden.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/parallax/grain.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/parallax/skyline.svg:
--------------------------------------------------------------------------------
1 | This design was made by vexels.com. It’s under CC 3.0 Attribution License. This means that for free use you must give credit and can’t do merchandise items. You can only do commercial and merchandise items without credit if you get a license. Learn more on www.vexels.com/plans You can’t sublicense, redistribute or resell an image or part of it. You can only use our contents for products where the design is the main reason it’s being purchased if you get a license. Learn more on www.vexels.com/terms-and-conditions Thanks! Vexels Team
--------------------------------------------------------------------------------
/public/patterns/black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/black.png
--------------------------------------------------------------------------------
/public/patterns/blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/blue.png
--------------------------------------------------------------------------------
/public/patterns/dots_blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/dots_blue.png
--------------------------------------------------------------------------------
/public/patterns/dots_green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/dots_green.png
--------------------------------------------------------------------------------
/public/patterns/dots_red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/dots_red.png
--------------------------------------------------------------------------------
/public/patterns/green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/green.png
--------------------------------------------------------------------------------
/public/patterns/red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/red.png
--------------------------------------------------------------------------------
/public/patterns/redstock.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/redstock.jpeg
--------------------------------------------------------------------------------
/public/patterns/stripes_green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/stripes_green.png
--------------------------------------------------------------------------------
/public/patterns/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/patterns/white.png
--------------------------------------------------------------------------------
/public/registration.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/registration.mp3
--------------------------------------------------------------------------------
/public/schedule.json:
--------------------------------------------------------------------------------
1 | {
2 | "events": [
3 | {
4 | "id": "d1ddaae9-5975-4b8c-84a5-1bb2991c1383",
5 | "name": "Hackathon Opening Ceremony",
6 | "description": "This is an event where things happen.",
7 | "time": {
8 | "start": "2022-07-22T18:00:00-07:00",
9 | "end": "2022-07-22T20:00:00-07:00"
10 | },
11 | "location": {
12 | "id": "ad029d24-0224-4f5d-b438-afd100f9393c",
13 | "name": "Figma HQ",
14 | "subplace": {
15 | "id": "ad029d24-0224-4f5d-b438-afd100f9393c",
16 | "name": "Inside"
17 | },
18 | "lat": 37.7821767,
19 | "long": -122.3915876
20 | },
21 | "imageLocation": "https://hackclub.com/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fgolden-train.9e4e38e9.png&w=2048&q=75"
22 | },
23 | {
24 | "id": "d1ddaae9-5975-4b8c-84a5-1bb2991c2383",
25 | "name": "Hackathon Opening Ceremony 2",
26 | "description": "This is an event where things happen. 2",
27 | "time": {
28 | "start": "2022-07-22T18:00:00-07:00",
29 | "end": "2022-07-22T20:00:00-07:00"
30 | },
31 | "location": {
32 | "id": "ad029d24-0224-4f5d-b438-afd1d0f9393c",
33 | "name": "Figma HQ 2",
34 | "subplace": {
35 | "id": "ad029d24-0224-4f5d-b438-afd1d0f9393c",
36 | "name": "Inside 2"
37 | },
38 | "lat": 37.7821767,
39 | "long": -122.3915876
40 | },
41 | "imageLocation": "https://hackclub.com/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fgolden-train.9e4e38e9.png&w=2048&q=75"
42 | }
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/public/social.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/social.png
--------------------------------------------------------------------------------
/public/textured-flag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/textured-flag.png
--------------------------------------------------------------------------------
/public/welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackclub/www-assemble/4097fd58d50ce453f81275a50e7739d8a973d70f/public/welcome.png
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "public": true,
3 | "github": { "silent": true }
4 | }
5 |
--------------------------------------------------------------------------------