mirror of
https://github.com/System-End/campfire.git
synced 2026-04-19 16:28:22 +00:00
feat: website json v2 + website updates
This commit is contained in:
parent
6049570d84
commit
9782423942
4 changed files with 653 additions and 451 deletions
|
|
@ -1,140 +1,150 @@
|
|||
{
|
||||
"hero": {
|
||||
"title": "CAMPFIRE",
|
||||
"city": "Shelburne",
|
||||
"subtitle": "Game jam for high schoolers in 200+ cities",
|
||||
"date": "Feb 28 - Mar 1, 2026",
|
||||
"emailPlaceholder": "you@hackclub.com",
|
||||
"ctaPrimary": "RSVP!",
|
||||
"ctaSecondary": "Find a Campfire near you",
|
||||
"ctaSecondaryPrefix": "Not in Shelburne? ",
|
||||
"ctaSecondarySuffix": ".",
|
||||
"videoLabel": "watch the video"
|
||||
},
|
||||
"nav": {
|
||||
"howToOrganize": "How to organize",
|
||||
"schedule": "Schedule",
|
||||
"gamesMade": "Games made",
|
||||
"faq": "FAQ"
|
||||
},
|
||||
"steps": {
|
||||
"step1": "Find a team of ",
|
||||
"step1Highlight": "CO-ORGANIZERS",
|
||||
"step1Suffix": " to help you organize your hackathon",
|
||||
"step2": "Find a ",
|
||||
"step2Highlight": "VENUE",
|
||||
"step2Suffix": " to host your hackathon",
|
||||
"step3": "Find ",
|
||||
"step3Highlight1": "SPONSORS",
|
||||
"step3Middle": " to buy merch and prizes, and make your event ",
|
||||
"step3Highlight2": "SPECIAL!",
|
||||
"step4": "Buy supplies, order food, learn ",
|
||||
"step4Highlight1": " GAME DEV",
|
||||
"step4Middle": ", and teach ",
|
||||
"step4Highlight2": "WORKSHOPS",
|
||||
"guideButton": "RSVP NOW"
|
||||
},
|
||||
"letter": {
|
||||
"greeting": "Dear hacker,",
|
||||
"paragraph1": "You can make a change: inspire someone to build a game for the first time, help someone fall in love with computers, run an incredible game jam that you can invite all your friends to.",
|
||||
"paragraph2": "This February, what if you organized a game jam in your city?",
|
||||
"paragraph3": "Hack Club will provide guides, funding, merch, and 1-on-1 mentorship. Our goal? Run 200 game jams in 200 cities worldwide. All on the same day. All run by high schoolers like us.",
|
||||
"paragraph4": "To kick off 2026, we're so excited to invite you to Campfire. In just a couple months, you will learn how to raise money for your event, buy food and drinks for your attendees, and make your own video games with your friends!",
|
||||
"paragraph5": "Let's go on an adventure together.",
|
||||
"closing": "With love,",
|
||||
"signature": "The Campfire Team"
|
||||
},
|
||||
"schedule": {
|
||||
"title": "SCHEDULE",
|
||||
"days": [
|
||||
{
|
||||
"date": "Feb 28th",
|
||||
"items": [
|
||||
{ "time": "7:45 AM", "activity": "Doors open" },
|
||||
{ "time": "8:00-8:45 AM", "activity": "Icebreakers" },
|
||||
{ "time": "9:00-9:45 AM", "activity": "Opening Ceremony" },
|
||||
{ "time": "10:15 AM-12:15 PM", "activity": "Godot Workshop" },
|
||||
{ "time": "12:45-1:45 PM", "activity": "Lunch" },
|
||||
{ "time": "2:00-3:00 PM", "activity": "Ren'py Workshop" },
|
||||
{ "time": "3:00-3:30 PM", "activity": "Hackathon Hosting 101 With Hack Canada" },
|
||||
{ "time": "4:00-4:15 PM", "activity": "Typing Contest" },
|
||||
{ "time": "6:00-7:00 PM", "activity": "Project Pitch and Dinner" },
|
||||
{ "time": "6:45-7:30 PM", "activity": "Just Dance" },
|
||||
{ "time": "7:35-7:45 PM", "activity": "Semi-Closing" }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"sponsors": {
|
||||
"title": "Our sponsors",
|
||||
"cards": [
|
||||
{
|
||||
"sponsor": "Hack Club",
|
||||
"logo": "https://assets.hackclub.com/flag-standalone-wtransparent.svg",
|
||||
"link": "https://hackclub.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
"signatures": false,
|
||||
"faq": {
|
||||
"title": "FAQ",
|
||||
"participant": {
|
||||
"title": "Participant",
|
||||
"questions": [
|
||||
{
|
||||
"question": "What is a game jam?",
|
||||
"answer": "A game jam is an event where you build a game from scratch in a short time period! It's all about creativity, teamwork, and having fun while learning new skills."
|
||||
},
|
||||
{
|
||||
"question": "Am I eligible?",
|
||||
"answer": "If you're a high schooler (or younger), you're eligible! No prior experience required - just bring your enthusiasm and willingness to learn."
|
||||
},
|
||||
{
|
||||
"question": "But I've never hacked before!",
|
||||
"answer": "Perfect! Game jams are designed for beginners. You'll have workshops, mentors, and teammates to help you every step of the way."
|
||||
},
|
||||
{
|
||||
"question": "All this, for free?",
|
||||
"answer": "Yes! Everything is completely free - venue, food, swag, workshops, and prizes. Hack Club covers all costs so you can focus on creating."
|
||||
},
|
||||
{
|
||||
"question": "What do I need to bring?",
|
||||
"answer": "Just bring yourself, a laptop, charger, and any personal items you need. We'll provide food, drinks, and everything else!"
|
||||
}
|
||||
],
|
||||
"buttonText": "Check out the parent guide"
|
||||
"version": 2,
|
||||
"localization": {
|
||||
"hero": {
|
||||
"campfire": "CAMPFIRE",
|
||||
"subtitle": "Game jam for high schoolers in 200+ cities",
|
||||
"hostedAt": "Hosted @ {venue}",
|
||||
"emailPlaceholder": "you@hackclub.com",
|
||||
"ctaPrimary": "SIGN UP!",
|
||||
"ctaSecondary": "flagship event",
|
||||
"ctaSecondaryPrefix": "Looking for our ",
|
||||
"ctaSecondarySuffix": "?",
|
||||
"videoLabel": "watch the video",
|
||||
"mapLabel": "find another event near you"
|
||||
},
|
||||
"organizer": {
|
||||
"title": "Organizer",
|
||||
"questions": [
|
||||
{
|
||||
"question": "Can I organize a Campfire in my city?",
|
||||
"answer": "Absolutely! We're always looking for passionate organizers. If you're ready to bring the magic of game development to your community, we'd love to help."
|
||||
},
|
||||
{
|
||||
"question": "What are the steps to organizing?",
|
||||
"answer": "First, apply through our organizer form. Then we'll guide you through venue booking, team building, workshop planning, and day-of coordination."
|
||||
},
|
||||
{
|
||||
"question": "Do we get funding?",
|
||||
"answer": "Yes! Hack Club provides funding for venue, food, swag, and other event costs. We want to remove financial barriers for amazing events."
|
||||
},
|
||||
{
|
||||
"question": "Do we get volunteer hours?",
|
||||
"answer": "Many schools accept organizing hours as community service. Check with your school's requirements - we can provide documentation."
|
||||
},
|
||||
{
|
||||
"question": "Can I join an organizing team?",
|
||||
"answer": "Of course! Many cities have organizing teams. Reach out to organizers in your area or apply to join an existing team."
|
||||
}
|
||||
],
|
||||
"buttonText": "Apply to be an organizer"
|
||||
"nav": {
|
||||
"steps": "Steps",
|
||||
"schedule": "Schedule",
|
||||
"games-made": "Games Made",
|
||||
"faq": "FAQ"
|
||||
},
|
||||
"schedule": {
|
||||
"title": "SCHEDULE"
|
||||
},
|
||||
"sponsors": {
|
||||
"title": "Our sponsors"
|
||||
},
|
||||
"signatures": {
|
||||
"title": "Signatures"
|
||||
},
|
||||
"steps": {
|
||||
"step1": "Sign up for a **Campfire** near you",
|
||||
"step2": "Grab **friends** (or make new friends!) and __form a__ **team of 2-3**",
|
||||
"step3": "Learn from **workshops**, enjoy __free food and merch!__",
|
||||
"step4": "**Build** your game & **publish** it on itch.io!",
|
||||
"guideButton": "READ MORE"
|
||||
},
|
||||
"letter": {
|
||||
"greeting": "Dear Hackers, Musicians, and Artists,",
|
||||
"paragraph1": "Welcome to Hack Club's newest adventure. This winter we invite you to join us for Campfire, the world's biggest Game Jam happening simultaneously in 200 cities.",
|
||||
"paragraph2": "Hack Club wants you to make a game this winter.",
|
||||
"paragraph3": "Don't consider yourself a game dev? No problem - we have tons of online and in-person workshops for you to make your first game!",
|
||||
"paragraph4": "This winter, we invite you to learn something new, make something you're really proud of, meet new friends, and go on an incredible adventure together.",
|
||||
"closing": "With love,",
|
||||
"signature": "The Campfire Team"
|
||||
},
|
||||
"footer": {
|
||||
"tagline": "made with love by Hack Club & Open Sauce",
|
||||
"copyright": "© 2026 Hack Club. 501(c)(3) nonprofit (EIN: 81-2908499)",
|
||||
"description": "Hack Club is a 501(c)(3) nonprofit and network of 60k+ technical high schoolers. We believe you learn best by building so we're creating community and providing grants so you can make awesome projects. In the past few years, we've partnered with GitHub to run ",
|
||||
"closing": "At Hack Club, students aren't just learning, they're shipping.",
|
||||
"links": [
|
||||
{ "text": "Hack Club", "href": "https://hackclub.com/" },
|
||||
{ "text": "Slack", "href": "https://hackclub.com/slack" },
|
||||
{ "text": "Clubs", "href": "https://hackclub.com/clubs" },
|
||||
{ "text": "Code of Conduct", "href": "https://hackclub.com/conduct/" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
"tagline": "made with love by Hack Club & Open Sauce",
|
||||
"copyright": "© 2026 Hack Club. 501(c)(3) nonprofit (EIN: 81-2908499)",
|
||||
"description": "Hack Club is a 501(c)(3) nonprofit and network of 60k+ technical high schoolers. We believe you learn best by building so we're creating community and providing grants so you can make awesome projects. In the past few years, we've partnered with GitHub to run ",
|
||||
"closing": "At Hack Club, students aren't just learning, they're shipping."
|
||||
"event": {
|
||||
"city": "Shelburne",
|
||||
"date": "Feb 28 - Mar 1, 2026",
|
||||
"venue": "Hack Club HQ",
|
||||
"schedule": {
|
||||
"days": [
|
||||
{
|
||||
"date": "Feb 28th",
|
||||
"items": [
|
||||
{ "time": "7:45 AM", "activity": "Doors open" },
|
||||
{ "time": "8:00-8:45 AM", "activity": "Icebreakers" },
|
||||
{ "time": "9:00-9:45 AM", "activity": "Opening Ceremony" },
|
||||
{ "time": "10:15 AM-12:15 PM", "activity": "Godot Workshop" },
|
||||
{ "time": "12:45-1:45 PM", "activity": "Lunch" },
|
||||
{ "time": "2:00-3:00 PM", "activity": "Ren'py Workshop" },
|
||||
{ "time": "3:00-3:30 PM", "activity": "Hackathon Hosting 101 With Hack Canada" },
|
||||
{ "time": "4:00-4:15 PM", "activity": "Typing Contest" },
|
||||
{ "time": "6:00-7:00 PM", "activity": "Project Pitch and Dinner" },
|
||||
{ "time": "6:45-7:30 PM", "activity": "Just Dance" },
|
||||
{ "time": "7:35-7:45 PM", "activity": "Semi-Closing" }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"sponsors": {
|
||||
"cards": [
|
||||
{
|
||||
"sponsor": "Hack Club",
|
||||
"logo": "https://assets.hackclub.com/flag-standalone-wtransparent.svg",
|
||||
"link": "https://hackclub.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
"signatures": false,
|
||||
"faq": {
|
||||
"title": "FAQ",
|
||||
"participant": {
|
||||
"title": "Participant",
|
||||
"questions": [
|
||||
{
|
||||
"question": "What is a game jam?",
|
||||
"answer": "A game jam is an event where you build a game from scratch in a short time period! It's all about creativity, teamwork, and having fun while learning new skills."
|
||||
},
|
||||
{
|
||||
"question": "Am I eligible?",
|
||||
"answer": "If you're a high schooler (or younger), you're eligible! No prior experience required - just bring your enthusiasm and willingness to learn."
|
||||
},
|
||||
{
|
||||
"question": "But I've never hacked before!",
|
||||
"answer": "Perfect! Game jams are designed for beginners. You'll have workshops, mentors, and teammates to help you every step of the way."
|
||||
},
|
||||
{
|
||||
"question": "All this, for free?",
|
||||
"answer": "Yes! Everything is completely free - venue, food, swag, workshops, and prizes. Hack Club covers all costs so you can focus on creating."
|
||||
},
|
||||
{
|
||||
"question": "What do I need to bring?",
|
||||
"answer": "Just bring yourself, a laptop, charger, and any personal items you need. We'll provide food, drinks, and everything else!"
|
||||
}
|
||||
],
|
||||
"buttonText": "Check out the parent guide"
|
||||
},
|
||||
"organizer": {
|
||||
"title": "Organizer",
|
||||
"questions": [
|
||||
{
|
||||
"question": "Can I organize a Campfire in my city?",
|
||||
"answer": "Absolutely! We're always looking for passionate organizers. If you're ready to bring the magic of game development to your community, we'd love to help."
|
||||
},
|
||||
{
|
||||
"question": "What are the steps to organizing?",
|
||||
"answer": "First, apply through our organizer form. Then we'll guide you through venue booking, team building, workshop planning, and day-of coordination."
|
||||
},
|
||||
{
|
||||
"question": "Do we get funding?",
|
||||
"answer": "Yes! Hack Club provides funding for venue, food, swag, and other event costs. We want to remove financial barriers for amazing events."
|
||||
},
|
||||
{
|
||||
"question": "Do we get volunteer hours?",
|
||||
"answer": "Many schools accept organizing hours as community service. Check with your school's requirements - we can provide documentation."
|
||||
},
|
||||
{
|
||||
"question": "Can I join an organizing team?",
|
||||
"answer": "Of course! Many cities have organizing teams. Reach out to organizers in your area or apply to join an existing team."
|
||||
}
|
||||
],
|
||||
"buttonText": "Apply to be an organizer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,162 +3,192 @@ import FaqButton from '../primitives/FaqButton.js';
|
|||
import Step from '../primitives/Step.js';
|
||||
import GameCard from '../primitives/GameCard.js';
|
||||
import NavbarLink from '../primitives/NavbarLink.tsx';
|
||||
import VideoEmbed from '../primitives/MapEmbed.tsx';
|
||||
import MapEmbed from '../primitives/MapEmbed.tsx';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import type { SatelliteContent } from '../../lib/satellite.ts';
|
||||
|
||||
function FormattedText({ text }: { text: string }) {
|
||||
const parts = text.split(/(\*\*[^*]+\*\*|__[^_]+__)/g);
|
||||
return (
|
||||
<>
|
||||
{parts.map((part, i) => {
|
||||
if (part.startsWith('**') && part.endsWith('**')) {
|
||||
return <span key={i} className="font-bold text-[#F77034]">{part.slice(2, -2)}</span>;
|
||||
}
|
||||
if (part.startsWith('__') && part.endsWith('__')) {
|
||||
return <span key={i} className="font-bold">{part.slice(2, -2)}</span>;
|
||||
}
|
||||
return part;
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const FORM_URL_ORGANIZER_APPLICATION = "https://forms.hackclub.com/t/8L51MzWyrHus";
|
||||
const FORM_URL_RSVP = "https://forms.hackclub.com/t/a3QSt8MuvHus";
|
||||
const FORM_URL_SIGN_UP = "https://forms.hackclub.com/campfire-signup";
|
||||
|
||||
const CONTENT = {
|
||||
hero: {
|
||||
title: "CAMPFIRE",
|
||||
city: "Shelburne",
|
||||
subtitle: "Game jam for high schoolers in 200+ cities",
|
||||
date: "Feb 28 - Mar 1, 2026",
|
||||
emailPlaceholder: "you@hackclub.com",
|
||||
ctaPrimary: "RSVP!",
|
||||
ctaSecondary: "Find a Campfire near you",
|
||||
ctaSecondaryPrefix: "Not in Shelburne? ",
|
||||
ctaSecondarySuffix: ".",
|
||||
videoLabel: "watch the video"
|
||||
},
|
||||
nav: {
|
||||
howToOrganize: "How to organize",
|
||||
schedule: "Schedule",
|
||||
gamesMade: "Games made",
|
||||
faq: "FAQ"
|
||||
},
|
||||
steps: {
|
||||
step1: "Find a team of ",
|
||||
step1Highlight: "CO-ORGANIZERS",
|
||||
step2: "Find a ",
|
||||
step2Highlight: "VENUE",
|
||||
step2Suffix: " to host your hackathon",
|
||||
step3: "Find ",
|
||||
step3Highlight1: "SPONSORS",
|
||||
step3Middle: " to buy merch and prizes, and make your event ",
|
||||
step3Highlight2: "SPECIAL!",
|
||||
step4: "Buy supplies, order food, learn ",
|
||||
step4Highlight1: " GAME DEV",
|
||||
step4Middle: ", and teach ",
|
||||
step4Highlight2: "WORKSHOPS",
|
||||
guideButton: "RSVP NOW"
|
||||
},
|
||||
letter: {
|
||||
greeting: "Dear hacker,",
|
||||
paragraph1: "You can make a change: inspire someone to build a game for the first time, help someone fall in love with computers, run an incredible game jam that you can invite all your friends to.",
|
||||
paragraph2: "This February, what if you organized a game jam in your city?",
|
||||
paragraph3: "Hack Club will provide guides, funding, merch, and 1-on-1 mentorship. Our goal? Run 200 game jams in 200 cities worldwide. All on the same day. All run by high schoolers like us.",
|
||||
paragraph4: "To kick off 2026, we're so excited to invite you to Campfire. In just a couple months, you will learn how to raise money for your event, buy food and drinks for your attendees, and make your own video games with your friends!",
|
||||
paragraph5: "Let's go on an adventure together.",
|
||||
closing: "With love,",
|
||||
signature: "The Campfire Team"
|
||||
},
|
||||
schedule: {
|
||||
title: "SCHEDULE",
|
||||
days: [
|
||||
{
|
||||
date: "Feb 28th",
|
||||
items: [
|
||||
{ time: "7:45 AM", activity: "Doors open" },
|
||||
{ time: "8:00-8:45 AM", activity: "Icebreakers" },
|
||||
{ time: "9:00-9:45 AM", activity: "Opening Ceremony" },
|
||||
{ time: "10:15 AM-12:15 PM", activity: "Godot Workshop" },
|
||||
{ time: "12:45-1:45 PM", activity: "Lunch" },
|
||||
{ time: "2:00-3:00 PM", activity: "Ren'py Workshop" },
|
||||
{ time: "3:00-3:30 PM", activity: "Hackathon Hosting 101 With Hack Canada" },
|
||||
{ time: "4:00-4:15 PM", activity: "Typing Contest" },
|
||||
{ time: "6:00-7:00 PM", activity: "Project Pitch and Dinner" },
|
||||
{ time: "6:45-7:30 PM", activity: "Just Dance" },
|
||||
{ time: "7:35-7:45 PM", activity: "Semi-Closing" },
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
sponsors: {
|
||||
title: "Our sponsors",
|
||||
cards: [
|
||||
{
|
||||
sponsor: "Hack Club",
|
||||
logo: "https://assets.hackclub.com/flag-standalone-wtransparent.svg",
|
||||
link: "https://hackclub.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
signatures: false as any,
|
||||
// signatures: {
|
||||
// title: "Campfire Shelburne is possible by...",
|
||||
// img: "https://assets.hackclub.com/flag-standalone-wtransparent.svg"
|
||||
// },
|
||||
faq: {
|
||||
title: "FAQ",
|
||||
participant: {
|
||||
title: "Participant",
|
||||
questions: [
|
||||
{
|
||||
question: "What is a game jam?",
|
||||
answer: "A game jam is an event where you build a game from scratch in a short time period! It's all about creativity, teamwork, and having fun while learning new skills."
|
||||
},
|
||||
{
|
||||
question: "Am I eligible?",
|
||||
answer: "If you're a high schooler (or younger), you're eligible! No prior experience required - just bring your enthusiasm and willingness to learn."
|
||||
},
|
||||
{
|
||||
question: "But I've never hacked before!",
|
||||
answer: "Perfect! Game jams are designed for beginners. You'll have workshops, mentors, and teammates to help you every step of the way."
|
||||
},
|
||||
{
|
||||
question: "All this, for free?",
|
||||
answer: "Yes! Everything is completely free - venue, food, swag, workshops, and prizes. Hack Club covers all costs so you can focus on creating."
|
||||
},
|
||||
{
|
||||
question: "What do I need to bring?",
|
||||
answer: "Just bring yourself, a laptop, charger, and any personal items you need. We'll provide food, drinks, and everything else!"
|
||||
}
|
||||
],
|
||||
buttonText: "Check out the parent guide"
|
||||
"version": 2,
|
||||
localization: {
|
||||
hero: {
|
||||
campfire: "CAMPFIRE",
|
||||
subtitle: "Game jam for high schoolers in 200+ cities",
|
||||
hostedAt: "Hosted @ {venue}",
|
||||
emailPlaceholder: "you@hackclub.com",
|
||||
ctaPrimary: "SIGN UP!",
|
||||
ctaSecondary: "flagship event",
|
||||
ctaSecondaryPrefix: "Looking for our ",
|
||||
ctaSecondarySuffix: "?",
|
||||
videoLabel: "watch the video",
|
||||
mapLabel: "find another event near you"
|
||||
},
|
||||
organizer: {
|
||||
title: "Organizer",
|
||||
questions: [
|
||||
{
|
||||
question: "Can I organize a Campfire in my city?",
|
||||
answer: "Absolutely! We're always looking for passionate organizers. If you're ready to bring the magic of game development to your community, we'd love to help."
|
||||
},
|
||||
{
|
||||
question: "What are the steps to organizing?",
|
||||
answer: "First, apply through our organizer form. Then we'll guide you through venue booking, team building, workshop planning, and day-of coordination."
|
||||
},
|
||||
{
|
||||
question: "Do we get funding?",
|
||||
answer: "Yes! Hack Club provides funding for venue, food, swag, and other event costs. We want to remove financial barriers for amazing events."
|
||||
},
|
||||
{
|
||||
question: "Do we get volunteer hours?",
|
||||
answer: "Many schools accept organizing hours as community service. Check with your school's requirements - we can provide documentation."
|
||||
},
|
||||
{
|
||||
question: "Can I join an organizing team?",
|
||||
answer: "Of course! Many cities have organizing teams. Reach out to organizers in your area or apply to join an existing team."
|
||||
}
|
||||
],
|
||||
buttonText: "Apply to be an organizer"
|
||||
nav: {
|
||||
'steps': "Steps",
|
||||
'schedule': "Schedule",
|
||||
'games-made': "Games Made",
|
||||
'faq': "FAQ"
|
||||
},
|
||||
schedule: {
|
||||
title: "SCHEDULE",
|
||||
},
|
||||
sponsors: {
|
||||
title: "Our sponsors",
|
||||
},
|
||||
signatures: {
|
||||
title: "Signatures",
|
||||
},
|
||||
steps: {
|
||||
step1: "Sign up for a **Campfire** near you",
|
||||
step2: "Grab **friends** (or make new friends!) and __form a__ **team of 2-3**",
|
||||
step3: "Learn from **workshops**, enjoy __free food and merch!__",
|
||||
step4: "**Build** your game & **publish** it on itch.io!",
|
||||
guideButton: "READ MORE"
|
||||
},
|
||||
letter: {
|
||||
greeting: "Dear Hackers, Musicians, and Artists,",
|
||||
paragraph1: "Welcome to Hack Club's newest adventure. This winter we invite you to join us for Campfire, the world's biggest Game Jam happening simultaneously in 200 cities.",
|
||||
paragraph2: "Hack Club wants you to make a game this winter.",
|
||||
paragraph3: "Don't consider yourself a game dev? No problem - we have tons of online and in-person workshops for you to make your first game!",
|
||||
paragraph4: "This winter, we invite you to learn something new, make something you're really proud of, meet new friends, and go on an incredible adventure together.",
|
||||
closing: "With love,",
|
||||
signature: "The Campfire Team"
|
||||
},
|
||||
footer: {
|
||||
tagline: "made with love by Hack Club & Open Sauce",
|
||||
copyright: "© 2026 Hack Club. 501(c)(3) nonprofit (EIN: 81-2908499)",
|
||||
description: "Hack Club is a 501(c)(3) nonprofit and network of 60k+ technical high schoolers. We believe you learn best by building so we're creating community and providing grants so you can make awesome projects. In the past few years, we've partnered with GitHub to run ",
|
||||
closing: "At Hack Club, students aren't just learning, they're shipping.",
|
||||
links: [
|
||||
{ text: "Hack Club", href: "https://hackclub.com/" },
|
||||
{ text: "Slack", href: "https://hackclub.com/slack" },
|
||||
{ text: "Clubs", href: "https://hackclub.com/clubs" },
|
||||
{ text: "Code of Conduct", href: "https://hackclub.com/conduct/" }
|
||||
]
|
||||
}
|
||||
},
|
||||
footer: {
|
||||
tagline: "made with love by Hack Club & Open Sauce",
|
||||
copyright: "© 2026 Hack Club. 501(c)(3) nonprofit (EIN: 81-2908499)",
|
||||
description: "Hack Club is a 501(c)(3) nonprofit and network of 60k+ technical high schoolers. We believe you learn best by building so we're creating community and providing grants so you can make awesome projects. In the past few years, we've partnered with GitHub to run ",
|
||||
closing: "At Hack Club, students aren't just learning, they're shipping."
|
||||
event: {
|
||||
city: "Shelburne",
|
||||
date: "Feb 28 - Mar 1, 2026",
|
||||
venue: "Hack Club HQ",
|
||||
schedule: {
|
||||
days: [
|
||||
{
|
||||
date: "Feb 28th",
|
||||
items: [
|
||||
{ time: "7:45 AM", activity: "Doors open" },
|
||||
{ time: "8:00-8:45 AM", activity: "Icebreakers" },
|
||||
{ time: "9:00-9:45 AM", activity: "Opening Ceremony" },
|
||||
{ time: "10:15 AM-12:15 PM", activity: "Godot Workshop" },
|
||||
{ time: "12:45-1:45 PM", activity: "Lunch" },
|
||||
{ time: "2:00-3:00 PM", activity: "Ren'py Workshop" },
|
||||
{ time: "3:00-3:30 PM", activity: "Hackathon Hosting 101 With Hack Canada" },
|
||||
{ time: "4:00-4:15 PM", activity: "Typing Contest" },
|
||||
{ time: "6:00-7:00 PM", activity: "Project Pitch and Dinner" },
|
||||
{ time: "6:45-7:30 PM", activity: "Just Dance" },
|
||||
{ time: "7:35-7:45 PM", activity: "Semi-Closing" },
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
sponsors: {
|
||||
cards: [
|
||||
{
|
||||
sponsor: "Hack Club",
|
||||
logo: "https://assets.hackclub.com/flag-standalone-wtransparent.svg",
|
||||
link: "https://hackclub.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
signatures: false as any,
|
||||
// signatures: {
|
||||
// title: "Campfire Shelburne is possible by...",
|
||||
// img: "https://assets.hackclub.com/flag-standalone-wtransparent.svg"
|
||||
// },
|
||||
faq: {
|
||||
title: "FAQ",
|
||||
participant: {
|
||||
title: "Participant",
|
||||
questions: [
|
||||
{
|
||||
question: "What is a game jam?",
|
||||
answer: "A game jam is an event where you build a game from scratch in a short time period! It's all about creativity, teamwork, and having fun while learning new skills."
|
||||
},
|
||||
{
|
||||
question: "Am I eligible?",
|
||||
answer: "If you're a high schooler (or younger), you're eligible! No prior experience required - just bring your enthusiasm and willingness to learn."
|
||||
},
|
||||
{
|
||||
question: "But I've never hacked before!",
|
||||
answer: "Perfect! Game jams are designed for beginners. You'll have workshops, mentors, and teammates to help you every step of the way."
|
||||
},
|
||||
{
|
||||
question: "All this, for free?",
|
||||
answer: "Yes! Everything is completely free - venue, food, swag, workshops, and prizes. Hack Club covers all costs so you can focus on creating."
|
||||
},
|
||||
{
|
||||
question: "What do I need to bring?",
|
||||
answer: "Just bring yourself, a laptop, charger, and any personal items you need. We'll provide food, drinks, and everything else!"
|
||||
}
|
||||
],
|
||||
buttonText: "Check out the parent guide"
|
||||
},
|
||||
organizer: {
|
||||
title: "Organizer",
|
||||
questions: [
|
||||
{
|
||||
question: "Can I organize a Campfire in my city?",
|
||||
answer: "Absolutely! We're always looking for passionate organizers. If you're ready to bring the magic of game development to your community, we'd love to help."
|
||||
},
|
||||
{
|
||||
question: "What are the steps to organizing?",
|
||||
answer: "First, apply through our organizer form. Then we'll guide you through venue booking, team building, workshop planning, and day-of coordination."
|
||||
},
|
||||
{
|
||||
question: "Do we get funding?",
|
||||
answer: "Yes! Hack Club provides funding for venue, food, swag, and other event costs. We want to remove financial barriers for amazing events."
|
||||
},
|
||||
{
|
||||
question: "Do we get volunteer hours?",
|
||||
answer: "Many schools accept organizing hours as community service. Check with your school's requirements - we can provide documentation."
|
||||
},
|
||||
{
|
||||
question: "Can I join an organizing team?",
|
||||
answer: "Of course! Many cities have organizing teams. Reach out to organizers in your area or apply to join an existing team."
|
||||
}
|
||||
],
|
||||
buttonText: "Apply to be an organizer"
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function App({slug, content}: {slug: string | undefined, content: SatelliteContent}) {
|
||||
const [email, setEmail] = useState("");
|
||||
const [scrollY, setScrollY] = useState(document.body.scrollTop);
|
||||
const [isLargeScreen, setIsLargeScreen] = useState(window.innerWidth >= 1280);
|
||||
const [isMapOpen, setIsMapOpen] = useState(false);
|
||||
const emailRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -203,12 +233,17 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
<div className="w-full h-screen">
|
||||
<header className="relative h-[60px] md:h-[115px] bg-[#45b4f5] justify-end items-center content-center md:pr-16 hidden sm:flex">
|
||||
<nav className="flex gap-4 w-full justify-between px-8 md:px-0 text-2xl md:gap-12 items-center md:justify-end text-white md:text-3xl xl:text-5xl font-bold font-ember-and-fire">
|
||||
<NavbarLink onClick={() => scrollToSection('steps')}>{content.nav.howToOrganize}</NavbarLink>
|
||||
{/* <NavbarLink onClick={() => scrollToSection('steps')}>{content.nav.howToOrganize}</NavbarLink> */}
|
||||
{/* <NavbarLink onClick={() => scrollToSection('map')}>Map</NavbarLink> */}
|
||||
{/* <NavbarLink onClick={() => scrollToSection('letter')}>Letter</NavbarLink> */}
|
||||
<NavbarLink onClick={() => scrollToSection('schedule')}>{content.nav.schedule}</NavbarLink>
|
||||
<NavbarLink onClick={() => scrollToSection('games-made')}>{content.nav.gamesMade}</NavbarLink>
|
||||
<NavbarLink onClick={() => scrollToSection('faq')}>{content.nav.faq}</NavbarLink>
|
||||
{/* <NavbarLink onClick={() => scrollToSection('schedule')}>{content.nav.schedule}</NavbarLink> */}
|
||||
{/* <NavbarLink onClick={() => scrollToSection('games-made')}>{content.nav.gamesMade}</NavbarLink> */}
|
||||
{/* <NavbarLink onClick={() => scrollToSection('faq')}>{content.nav.faq}</NavbarLink> */}
|
||||
{
|
||||
Object.keys(content.localization.nav).map(key => (
|
||||
<NavbarLink key={key} onClick={() => scrollToSection(key)}>{content.localization.nav[key]}</NavbarLink>
|
||||
))
|
||||
}
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
|
@ -245,14 +280,6 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
/>
|
||||
</div>
|
||||
|
||||
<div className="absolute -bottom-[50px] left-0 w-full h-[120px] pointer-events-none">
|
||||
<img
|
||||
src="/decorative/vines.webp"
|
||||
alt=""
|
||||
className="w-full h-full object-cover object-top select-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-between items-center md:items-start xl:items-center w-full gap-8 pb-16 z-30 h-full pt-16 md:pt-0 md:h-auto">
|
||||
<div className="flex flex-col gap-4 w-full md:w-[648px]">
|
||||
<div className="mb-6">
|
||||
|
|
@ -287,7 +314,7 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "5px 8px 0px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.hero.title}
|
||||
{content.localization.hero.campfire}
|
||||
</h1>
|
||||
<h3
|
||||
className="text-[#fcf5ed] text-[40px] md:text-[50px] xl:text-[60px] font-normal leading-none mb-4 font-dream-planner text-right"
|
||||
|
|
@ -295,7 +322,7 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "5px 8px 0px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.hero.city.toUpperCase()}
|
||||
{content.event.city.toUpperCase()}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
|
|
@ -306,7 +333,15 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.hero.subtitle}
|
||||
{content.localization.hero.subtitle}
|
||||
</p>
|
||||
<p
|
||||
className="text-white text-4xl md:text-3xl xl:text-4xl font-bold mb-2 font-ember-and-fire"
|
||||
style={{
|
||||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.localization.hero.hostedAt.replace('{venue}', content.event.venue)}
|
||||
</p>
|
||||
<p
|
||||
className="text-white text-4xl md:text-3xl xl:text-4xl font-bold font-ember-and-fire"
|
||||
|
|
@ -314,7 +349,7 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.hero.date}
|
||||
{content.event.date}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -335,20 +370,19 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
onChange={e => setEmail(e.target.value)}
|
||||
type="email"
|
||||
className="text-[#854d16] text-2xl md:text-4xl font-bold truncate bg-transparent border-none outline-none flex-1 cursor-text font-ember-and-fire"
|
||||
placeholder={content.hero.emailPlaceholder}
|
||||
defaultValue={content.hero.emailPlaceholder}
|
||||
placeholder={content.localization.hero.emailPlaceholder}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
<button
|
||||
className="bg-[#fca147] border-[5px] border-[rgba(0,0,0,0.2)] rounded-[20px] px-8 md:px-14 py-4 hover:scale-105 transition-transform w-full md:w-auto transform md:rotate-[1.5deg] shadow-[0_8px_20px_rgba(0,0,0,0.25)] cursor-pointer active:scale-95"
|
||||
type="button"
|
||||
onClick={() => openWithEmail(FORM_URL_ORGANIZER_APPLICATION)}
|
||||
onClick={() => openWithEmail(FORM_URL_SIGN_UP)}
|
||||
>
|
||||
<p
|
||||
className="text-[#8d3f34] text-3xl md:text-5xl font-normal font-dream-planner"
|
||||
<p
|
||||
className="text-[#8d3f34] text-3xl md:text-5xl font-normal font-dream-planner whitespace-nowrap"
|
||||
>
|
||||
{content.hero.ctaPrimary}
|
||||
{content.localization.hero.ctaPrimary}
|
||||
</p>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -356,17 +390,17 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
<div className='font-ember-and-fire text-white text-4xl pl-2 -translate-y-1 md:rotate-[-1.2deg]' style={{
|
||||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}>
|
||||
{content.hero.ctaSecondaryPrefix}<span
|
||||
{content.localization.hero.ctaSecondaryPrefix}<span
|
||||
className='underline inline-block cursor-pointer transition-transform hover:scale-105 active:scale-95'
|
||||
onClick={() => openWithEmail(FORM_URL_RSVP)}
|
||||
>
|
||||
{content.hero.ctaSecondary}
|
||||
</span>{content.hero.ctaSecondarySuffix}
|
||||
{content.localization.hero.ctaSecondary}
|
||||
</span>{content.localization.hero.ctaSecondarySuffix}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<VideoEmbed className="hidden xl:block self-end mb-8" />
|
||||
<MapEmbed className="hidden xl:block self-end mb-8" onOpenMap={() => setIsMapOpen(true)} label={content.localization.hero.mapLabel}/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -383,8 +417,8 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
</div>
|
||||
|
||||
<section className="relative pb-96 bg-[url(/backgrounds/underwater-gradient.webp)] bg-cover bg-top">
|
||||
<div className="xl:hidden pt-16 pb-8 relative z-10">
|
||||
<VideoEmbed className="px-6" />
|
||||
<div className="xl:hidden pt-16 pb-8 relative z-50">
|
||||
<MapEmbed className="px-6 relative z-50 max-w-sm mx-auto" onOpenMap={() => setIsMapOpen(true)} label={content.localization.hero.mapLabel}/>
|
||||
</div>
|
||||
<div className="pt-[8vw] xl:pt-[13vw]"></div>
|
||||
<div className="absolute top-0 left-0 w-screen h-[200px] bg-gradient-to-b from-[#004b2a] to-transparent pointer-events-none"></div>
|
||||
|
|
@ -433,7 +467,7 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
imageSrc="/compressed/ui/step-signup.jpeg"
|
||||
imageAlt="Step 1"
|
||||
>
|
||||
{content.steps.step1}<br></br><span className="font-bold text-[#F77034]">{content.steps.step1Highlight}</span>
|
||||
<FormattedText text={content.localization.steps.step1} />
|
||||
</Step>
|
||||
|
||||
<Step
|
||||
|
|
@ -442,7 +476,7 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
imageAlt="Step 2"
|
||||
isReversed={true}
|
||||
>
|
||||
{content.steps.step2}<span className="font-bold text-[#F77034]">{content.steps.step2Highlight}</span>{content.steps.step2Suffix}
|
||||
<FormattedText text={content.localization.steps.step2} />
|
||||
</Step>
|
||||
|
||||
<Step
|
||||
|
|
@ -450,7 +484,7 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
imageSrc="/compressed/ui/step-workshops.webp"
|
||||
imageAlt="Step 3"
|
||||
>
|
||||
{content.steps.step3}<span className="text-[#F77034] font-bold">{content.steps.step3Highlight1}</span>{content.steps.step3Middle}<span className="text-[#F77034] font-bold">{content.steps.step3Highlight2}</span>
|
||||
<FormattedText text={content.localization.steps.step3} />
|
||||
</Step>
|
||||
|
||||
<Step
|
||||
|
|
@ -459,23 +493,8 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
imageAlt="Step 4"
|
||||
isReversed={true}
|
||||
>
|
||||
{content.steps.step4}<span className="text-[#F77034] font-bold">{content.steps.step4Highlight1}</span>{content.steps.step4Middle}<span className="text-[#F77034] font-bold">{content.steps.step4Highlight2}</span>
|
||||
<FormattedText text={content.localization.steps.step4} />
|
||||
</Step>
|
||||
|
||||
<div className="flex justify-end mt-12">
|
||||
<button
|
||||
className="bg-[#E77232] rounded-[20px] px-16 py-8 transform rotate-[2deg] hover:scale-105 transition-transform shadow-[0_8px_20px_rgba(0,0,0,0.25)] cursor-pointer active:scale-95 animate-float-up-down"
|
||||
type="button"
|
||||
onClick={() => window.open("https://docs.google.com/document/d/14sMLsvxpBFtdzNOvmMJyjIrggKdaXLJ2GMiOoBcE8-M/", "_blank")}
|
||||
>
|
||||
<p
|
||||
className="text-5xl md:text-6xl font-normal font-dream-planner"
|
||||
style={{ color: "rgba(255, 255, 255, 0.69)" }}
|
||||
>
|
||||
{content.steps.guideButton}
|
||||
</p>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -489,20 +508,18 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
<div className='flex items-center min-[1200px]:block min-[1200px]:relative'>
|
||||
<img src='/backgrounds/world-map-right.webp' alt='' className='h-full hidden min-[1200px]:block' />
|
||||
<div className='min-[1200px]:absolute min-[1200px]:top-0 min-[1200px]:left-0 py-12 min-[1200px]:py-16 min-[1200px]:pb-0 rounded-xl shadow-[0_8px_20px_rgba(0,0,0,0.25)] min-[1200px]:rounded-none min-[1200px]:shadow-none min-[1200px]:pt-30 pl-6 min-[1200px]:pl-12 pr-6 min-[1200px]:pr-64 text-xl bg-[#EAD6BE] border-[#DCA87E] border-4 min-[1200px]:border-0 min-[1200px]:bg-transparent flex flex-col gap-6 font-solway'>
|
||||
<h1>{content.letter.greeting}</h1>
|
||||
<p>{content.letter.paragraph1}</p>
|
||||
<h1 className="text-2xl md:text-3xl font-bold">{content.localization.letter.greeting}</h1>
|
||||
<p>{content.localization.letter.paragraph1}</p>
|
||||
|
||||
<p><b>{content.letter.paragraph2}</b></p>
|
||||
<p className="text-xl"><b>{content.localization.letter.paragraph2}</b></p>
|
||||
|
||||
<p>{content.letter.paragraph3}</p>
|
||||
<p>{content.localization.letter.paragraph3}</p>
|
||||
|
||||
<p>{content.letter.paragraph4}</p>
|
||||
|
||||
<p>{content.letter.paragraph5}</p>
|
||||
<p>{content.localization.letter.paragraph4}</p>
|
||||
|
||||
<p>
|
||||
{content.letter.closing} <br />
|
||||
{content.letter.signature}
|
||||
{content.localization.letter.closing} <br />
|
||||
{content.localization.letter.signature}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -542,11 +559,11 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
<h2
|
||||
className="text-[#FFD999] text-6xl md:text-7xl font-bold text-center mb-4 font-ember-and-fire relative z-10"
|
||||
>
|
||||
{content.schedule.title}
|
||||
{content.localization.schedule.title}
|
||||
</h2>
|
||||
|
||||
<div className="relative z-10 max-w-4xl mx-auto flex flex-col gap-8">
|
||||
{content.schedule.days.map((day, dayIndex) => (
|
||||
{content.event.schedule.days.map((day, dayIndex) => (
|
||||
<div key={dayIndex}>
|
||||
<h3 className="text-[#FFD999] text-2xl md:text-3xl font-bold font-ember-and-fire mb-4">
|
||||
{day.date}
|
||||
|
|
@ -586,12 +603,12 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.sponsors.title}
|
||||
{content.localization.sponsors.title}
|
||||
</h2>
|
||||
|
||||
<div className="flex flex-wrap gap-8 justify-center">
|
||||
{
|
||||
content.sponsors.cards.map((sponsor, index) => (
|
||||
content.event.sponsors.cards.map((sponsor, index) => (
|
||||
<>
|
||||
<a key={index} href={sponsor.link} target="_blank" className='flex flex-col justify-center items-center bg-white/10 rounded-xl p-4 hover:bg-white/15 transition-all'>
|
||||
<img
|
||||
|
|
@ -607,7 +624,7 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
</div>
|
||||
|
||||
{
|
||||
content.signatures ?
|
||||
content.event.signatures ?
|
||||
(
|
||||
<div>
|
||||
<h2
|
||||
|
|
@ -617,12 +634,12 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.signatures.title}
|
||||
{content.localization.signatures.title}
|
||||
</h2>
|
||||
|
||||
<img
|
||||
src={content.signatures.img}
|
||||
alt={content.signatures.title}
|
||||
src={content.event.signatures.img}
|
||||
alt={content.localization.signatures.title}
|
||||
className="w-[60%] object-cover select-none"
|
||||
/>
|
||||
</div>)
|
||||
|
|
@ -656,7 +673,7 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.faq.title}
|
||||
{content.event.faq.title}
|
||||
</h2>
|
||||
|
||||
<div className="flex flex-col md:flex-row gap-32 md:gap-10 justify-center items-center md:items-start">
|
||||
|
|
@ -674,15 +691,15 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.faq.participant.title}
|
||||
{content.event.faq.participant.title}
|
||||
</p>
|
||||
|
||||
{content.faq.participant.questions.map((q, i) => (
|
||||
{content.event.faq.participant.questions.map((q, i) => (
|
||||
<FaqQuestion key={i} question={q.question}>
|
||||
{q.answer}
|
||||
</FaqQuestion>
|
||||
))}
|
||||
<FaqButton content={content.faq.participant.buttonText} />
|
||||
<FaqButton content={content.event.faq.participant.buttonText} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -700,15 +717,15 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.faq.organizer.title}
|
||||
{content.event.faq.organizer.title}
|
||||
</p>
|
||||
|
||||
{content.faq.organizer.questions.map((q, i) => (
|
||||
{content.event.faq.organizer.questions.map((q, i) => (
|
||||
<FaqQuestion key={i} question={q.question}>
|
||||
{q.answer}
|
||||
</FaqQuestion>
|
||||
))}
|
||||
<FaqButton href={FORM_URL_ORGANIZER_APPLICATION} content={content.faq.organizer.buttonText} />
|
||||
<FaqButton href={FORM_URL_ORGANIZER_APPLICATION} content={content.event.faq.organizer.buttonText} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -729,32 +746,54 @@ function App({slug, content}: {slug: string | undefined, content: SatelliteConte
|
|||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
{content.footer.tagline}
|
||||
{content.localization.footer.tagline}
|
||||
</p>
|
||||
|
||||
<div className="mt-8 flex flex-col md:flex-row gap-16 max-w-6xl mx-auto px-4">
|
||||
<div className="flex flex-col items-center md:items-end gap-4 text-white text-4xl md:text-3xl font-ember-and-fire font-bold z-20">
|
||||
<a href="https://hackclub.com/" target="_blank" className="hover:underline">Hack Club</a>
|
||||
<a href="https://hackclub.com/slack" target="_blank" className="hover:underline">Slack</a>
|
||||
<a href="https://hackclub.com/clubs" target="_blank" className="hover:underline">Clubs</a>
|
||||
<a href="https://hackclub.com/conduct/" target="_blank" className="hover:underline">Code of Conduct</a>
|
||||
{content.localization.footer.links.map((link, index) => (
|
||||
<a key={index} href={link.href} target="_blank" className="hover:underline">{link.text}</a>
|
||||
))}
|
||||
|
||||
<p className="text-white text-sm md:text-md text-right max-w-96 font-ember-and-fire">
|
||||
{content.footer.copyright}
|
||||
{content.localization.footer.copyright}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 text-left">
|
||||
<p className="text-white text-lg md:text-xl font-ember-and-fire leading-relaxed mb-4">
|
||||
{content.footer.description}<a href="https://summer.hackclub.com/" target="_blank" className="underline hover:text-gray-300">Summer of Making</a>, hosted the <a href="https://github.com/hackclub/the-hacker-zephyr" target="_blank" className="underline hover:text-gray-300">world's longest hackathon on land</a>, and ran <a href="https://www.youtube.com/watch?v=QvCoISXfcE8" target="_blank" className="underline hover:text-gray-300">Canada's largest high school hackathon</a>.
|
||||
{content.localization.footer.description}<a href="https://summer.hackclub.com/" target="_blank" className="underline hover:text-gray-300">Summer of Making</a>, hosted the <a href="https://github.com/hackclub/the-hacker-zephyr" target="_blank" className="underline hover:text-gray-300">world's longest hackathon on land</a>, and ran <a href="https://www.youtube.com/watch?v=QvCoISXfcE8" target="_blank" className="underline hover:text-gray-300">Canada's largest high school hackathon</a>.
|
||||
</p>
|
||||
<p className="text-white text-lg md:text-xl font-ember-and-fire font-bold">
|
||||
{content.footer.closing}
|
||||
{content.localization.footer.closing}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
{isMapOpen && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/80 z-[9999] flex items-center justify-center p-4"
|
||||
onClick={() => setIsMapOpen(false)}
|
||||
>
|
||||
<div
|
||||
className="relative w-[90vw] h-[80vh]"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<button
|
||||
onClick={() => setIsMapOpen(false)}
|
||||
className="absolute -top-10 right-0 text-white text-3xl font-bold hover:opacity-70 cursor-pointer"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
<iframe
|
||||
src="/map"
|
||||
className="w-full h-full rounded-2xl"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,26 @@
|
|||
interface MapEmbedProps {
|
||||
className?: string;
|
||||
label?: string;
|
||||
onOpenMap: () => void;
|
||||
}
|
||||
|
||||
function MapEmbed({ className, onOpenMap }: MapEmbedProps) {
|
||||
function MapEmbed({ className, onOpenMap, label = "find an event near you" }: MapEmbedProps) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="flex items-center justify-center gap-3 mb-4 2xl:mb-8">
|
||||
<div className="relative mt-16 md:mt-0 mb-2 md:mb-10 2xl:mb-12">
|
||||
<p
|
||||
className="text-white text-3xl 2xl:text-5xl font-bold font-ember-and-fire"
|
||||
className="text-white text-4xl 2xl:text-5xl font-bold font-ember-and-fire text-center"
|
||||
style={{
|
||||
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||
}}
|
||||
>
|
||||
find an event near you
|
||||
{label}
|
||||
</p>
|
||||
|
||||
<img
|
||||
src="/compressed/ui/arrow.webp"
|
||||
alt=""
|
||||
className="w-[45px] md:w-[55px] h-[33px] md:h-[41px] translate-y-6 rotate-[6.2deg] z-50 select-none"
|
||||
className="hidden md:block absolute right-0 top-full w-[55px] h-[41px] rotate-[6.2deg] z-50 select-none"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,101 +18,253 @@ export async function getSatelliteData(slug: string) {
|
|||
});
|
||||
}
|
||||
|
||||
// {
|
||||
// "version": 2,
|
||||
// localization: {
|
||||
// hero: {
|
||||
// campfire: "CAMPFIRE",
|
||||
// subtitle: "Game jam for high schoolers in 200+ cities",
|
||||
// hostedAt: "Hosted @ {venue}",
|
||||
// emailPlaceholder: "you@hackclub.com",
|
||||
// ctaPrimary: "SIGN UP!",
|
||||
// ctaSecondary: "Find a Campfire near you",
|
||||
// ctaSecondaryPrefix: "Not in Shelburne? ",
|
||||
// ctaSecondarySuffix: ".",
|
||||
// videoLabel: "watch the video"
|
||||
// },
|
||||
// nav: {
|
||||
// "Steps": 'steps',
|
||||
// "Schedule": 'schedule',
|
||||
// "Games Made": 'games-made',
|
||||
// "FAQ": 'faq'
|
||||
// },
|
||||
// steps: {
|
||||
// step1: "Find a team of ",
|
||||
// step1Highlight: "CO-ORGANIZERS",
|
||||
// step2: "Find a ",
|
||||
// step2Highlight: "VENUE",
|
||||
// step2Suffix: " to host your hackathon",
|
||||
// step3: "Find ",
|
||||
// step3Highlight1: "SPONSORS",
|
||||
// step3Middle: " to buy merch and prizes, and make your event ",
|
||||
// step3Highlight2: "SPECIAL!",
|
||||
// step4: "Buy supplies, order food, learn ",
|
||||
// step4Highlight1: " GAME DEV",
|
||||
// step4Middle: ", and teach ",
|
||||
// step4Highlight2: "WORKSHOPS",
|
||||
// guideButton: "RSVP NOW"
|
||||
// },
|
||||
// letter: {
|
||||
// greeting: "Dear hacker,",
|
||||
// paragraph1: "You can make a change: inspire someone to build a game for the first time, help someone fall in love with computers, run an incredible game jam that you can invite all your friends to.",
|
||||
// paragraph2: "This February, what if you organized a game jam in your city?",
|
||||
// paragraph3: "Hack Club will provide guides, funding, merch, and 1-on-1 mentorship. Our goal? Run 200 game jams in 200 cities worldwide. All on the same day. All run by high schoolers like us.",
|
||||
// paragraph4: "To kick off 2026, we're so excited to invite you to Campfire. In just a couple months, you will learn how to raise money for your event, buy food and drinks for your attendees, and make your own video games with your friends!",
|
||||
// paragraph5: "Let's go on an adventure together.",
|
||||
// closing: "With love,",
|
||||
// signature: "The Campfire Team"
|
||||
// },
|
||||
// footer: {
|
||||
// tagline: "made with love by Hack Club & Open Sauce",
|
||||
// copyright: "© 2026 Hack Club. 501(c)(3) nonprofit (EIN: 81-2908499)",
|
||||
// description: "Hack Club is a 501(c)(3) nonprofit and network of 60k+ technical high schoolers. We believe you learn best by building so we're creating community and providing grants so you can make awesome projects. In the past few years, we've partnered with GitHub to run ",
|
||||
// closing: "At Hack Club, students aren't just learning, they're shipping."
|
||||
// }
|
||||
// },
|
||||
// event: {
|
||||
// city: "Shelburne",
|
||||
// date: "Feb 28 - Mar 1, 2026",
|
||||
// venue: "Hack Club HQ",
|
||||
// schedule: {
|
||||
// title: "SCHEDULE",
|
||||
// days: [
|
||||
// {
|
||||
// date: "Feb 28th",
|
||||
// items: [
|
||||
// { time: "7:45 AM", activity: "Doors open" },
|
||||
// { time: "8:00-8:45 AM", activity: "Icebreakers" },
|
||||
// { time: "9:00-9:45 AM", activity: "Opening Ceremony" },
|
||||
// { time: "10:15 AM-12:15 PM", activity: "Godot Workshop" },
|
||||
// { time: "12:45-1:45 PM", activity: "Lunch" },
|
||||
// { time: "2:00-3:00 PM", activity: "Ren'py Workshop" },
|
||||
// { time: "3:00-3:30 PM", activity: "Hackathon Hosting 101 With Hack Canada" },
|
||||
// { time: "4:00-4:15 PM", activity: "Typing Contest" },
|
||||
// { time: "6:00-7:00 PM", activity: "Project Pitch and Dinner" },
|
||||
// { time: "6:45-7:30 PM", activity: "Just Dance" },
|
||||
// { time: "7:35-7:45 PM", activity: "Semi-Closing" },
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// sponsors: {
|
||||
// title: "Our sponsors",
|
||||
// cards: [
|
||||
// {
|
||||
// sponsor: "Hack Club",
|
||||
// logo: "https://assets.hackclub.com/flag-standalone-wtransparent.svg",
|
||||
// link: "https://hackclub.com"
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// signatures: false as any,
|
||||
// // signatures: {
|
||||
// // title: "Campfire Shelburne is possible by...",
|
||||
// // img: "https://assets.hackclub.com/flag-standalone-wtransparent.svg"
|
||||
// // },
|
||||
// faq: {
|
||||
// title: "FAQ",
|
||||
// participant: {
|
||||
// title: "Participant",
|
||||
// questions: [
|
||||
// {
|
||||
// question: "What is a game jam?",
|
||||
// answer: "A game jam is an event where you build a game from scratch in a short time period! It's all about creativity, teamwork, and having fun while learning new skills."
|
||||
// },
|
||||
// {
|
||||
// question: "Am I eligible?",
|
||||
// answer: "If you're a high schooler (or younger), you're eligible! No prior experience required - just bring your enthusiasm and willingness to learn."
|
||||
// },
|
||||
// {
|
||||
// question: "But I've never hacked before!",
|
||||
// answer: "Perfect! Game jams are designed for beginners. You'll have workshops, mentors, and teammates to help you every step of the way."
|
||||
// },
|
||||
// {
|
||||
// question: "All this, for free?",
|
||||
// answer: "Yes! Everything is completely free - venue, food, swag, workshops, and prizes. Hack Club covers all costs so you can focus on creating."
|
||||
// },
|
||||
// {
|
||||
// question: "What do I need to bring?",
|
||||
// answer: "Just bring yourself, a laptop, charger, and any personal items you need. We'll provide food, drinks, and everything else!"
|
||||
// }
|
||||
// ],
|
||||
// buttonText: "Check out the parent guide"
|
||||
// },
|
||||
// organizer: {
|
||||
// title: "Organizer",
|
||||
// questions: [
|
||||
// {
|
||||
// question: "Can I organize a Campfire in my city?",
|
||||
// answer: "Absolutely! We're always looking for passionate organizers. If you're ready to bring the magic of game development to your community, we'd love to help."
|
||||
// },
|
||||
// {
|
||||
// question: "What are the steps to organizing?",
|
||||
// answer: "First, apply through our organizer form. Then we'll guide you through venue booking, team building, workshop planning, and day-of coordination."
|
||||
// },
|
||||
// {
|
||||
// question: "Do we get funding?",
|
||||
// answer: "Yes! Hack Club provides funding for venue, food, swag, and other event costs. We want to remove financial barriers for amazing events."
|
||||
// },
|
||||
// {
|
||||
// question: "Do we get volunteer hours?",
|
||||
// answer: "Many schools accept organizing hours as community service. Check with your school's requirements - we can provide documentation."
|
||||
// },
|
||||
// {
|
||||
// question: "Can I join an organizing team?",
|
||||
// answer: "Of course! Many cities have organizing teams. Reach out to organizers in your area or apply to join an existing team."
|
||||
// }
|
||||
// ],
|
||||
// buttonText: "Apply to be an organizer"
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
|
||||
export type SatelliteContent = {
|
||||
hero: {
|
||||
title: string;
|
||||
city: string;
|
||||
subtitle: string;
|
||||
date: string;
|
||||
emailPlaceholder: string;
|
||||
ctaPrimary: string;
|
||||
ctaSecondary: string;
|
||||
ctaSecondaryPrefix: string;
|
||||
ctaSecondarySuffix: string;
|
||||
videoLabel: string;
|
||||
},
|
||||
nav: {
|
||||
howToOrganize: string;
|
||||
schedule: string;
|
||||
gamesMade: string;
|
||||
faq: string;
|
||||
},
|
||||
steps: {
|
||||
step1: string;
|
||||
step1Highlight: string;
|
||||
step1Suffix: string;
|
||||
step2: string;
|
||||
step2Highlight: string;
|
||||
step2Suffix: string;
|
||||
step3: string;
|
||||
step3Highlight1: string;
|
||||
step3Middle: string;
|
||||
step3Highlight2: string;
|
||||
step3Suffix: string;
|
||||
step4: string;
|
||||
step4Highlight1: string;
|
||||
step4Middle: string;
|
||||
step4Highlight2: string;
|
||||
step4Suffix: string;
|
||||
guideButton: string;
|
||||
},
|
||||
letter: {
|
||||
greeting: string;
|
||||
paragraph1: string;
|
||||
paragraph2: string;
|
||||
paragraph3: string;
|
||||
paragraph4: string;
|
||||
paragraph5: string;
|
||||
closing: string;
|
||||
signature: string;
|
||||
},
|
||||
schedule: {
|
||||
title: string;
|
||||
days: {
|
||||
date: string;
|
||||
items: {
|
||||
time: string;
|
||||
activity: string;
|
||||
}[];
|
||||
}[];
|
||||
},
|
||||
sponsors: {
|
||||
title: string;
|
||||
cards: {
|
||||
sponsor: string;
|
||||
logo: string;
|
||||
link: string;
|
||||
}[];
|
||||
},
|
||||
signatures?: {
|
||||
title: string;
|
||||
img: string;
|
||||
};
|
||||
faq: {
|
||||
title: string;
|
||||
participant: {
|
||||
localization: {
|
||||
hero: {
|
||||
campfire: string;
|
||||
subtitle: string;
|
||||
hostedAt: string;
|
||||
emailPlaceholder: string;
|
||||
ctaPrimary: string;
|
||||
ctaSecondary: string;
|
||||
ctaSecondaryPrefix: string;
|
||||
ctaSecondarySuffix: string;
|
||||
videoLabel?: string;
|
||||
mapLabel: string;
|
||||
};
|
||||
nav: {
|
||||
[key: string]: string;
|
||||
};
|
||||
steps: {
|
||||
step1: string;
|
||||
step2: string;
|
||||
step3: string;
|
||||
step4: string;
|
||||
guideButton: string;
|
||||
};
|
||||
letter: {
|
||||
greeting: string;
|
||||
paragraph1: string;
|
||||
paragraph2: string;
|
||||
paragraph3: string;
|
||||
paragraph4: string;
|
||||
closing: string;
|
||||
signature: string;
|
||||
};
|
||||
schedule: {
|
||||
title: string;
|
||||
questions: {
|
||||
question: string;
|
||||
answer: string;
|
||||
}[];
|
||||
buttonText: string;
|
||||
},
|
||||
organizer: {
|
||||
title: string;
|
||||
questions: {
|
||||
question: string;
|
||||
answer: string;
|
||||
}[];
|
||||
buttonText: string;
|
||||
}
|
||||
},
|
||||
footer: {
|
||||
tagline: string;
|
||||
copyright: string;
|
||||
description: string;
|
||||
closing: string;
|
||||
}
|
||||
sponsors: {
|
||||
title: string;
|
||||
}
|
||||
signatures: {
|
||||
title: string;
|
||||
}
|
||||
footer: {
|
||||
tagline: string;
|
||||
copyright: string;
|
||||
description: string;
|
||||
closing: string;
|
||||
links: {
|
||||
text: string;
|
||||
href: string;
|
||||
}[];
|
||||
};
|
||||
};
|
||||
event: {
|
||||
city: string;
|
||||
date: string;
|
||||
venue: string;
|
||||
schedule: {
|
||||
days: {
|
||||
date: string;
|
||||
items: {
|
||||
time: string;
|
||||
activity: string;
|
||||
}[];
|
||||
}[];
|
||||
};
|
||||
sponsors: {
|
||||
cards: {
|
||||
sponsor: string;
|
||||
logo: string;
|
||||
link: string;
|
||||
}[];
|
||||
};
|
||||
signatures?: false | {
|
||||
img: string;
|
||||
}
|
||||
faq: {
|
||||
title: string;
|
||||
participant: {
|
||||
title: string;
|
||||
questions: {
|
||||
question: string;
|
||||
answer: string;
|
||||
}[];
|
||||
buttonText: string;
|
||||
};
|
||||
organizer: {
|
||||
title: string;
|
||||
questions: {
|
||||
question: string;
|
||||
answer: string;
|
||||
}[];
|
||||
buttonText: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// setSatelliteData('shelburne', {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue