Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
29f7ce9
khix hero set up and parallax
Adr1an04 Jun 23, 2026
b6cf50d
navbar and pond anim
Adr1an04 Jun 24, 2026
39fc679
hello
cataladev Jun 24, 2026
1aee43c
about section start
Adr1an04 Jun 27, 2026
a74d0e2
added khix team cascade test page
cataladev Jun 30, 2026
fc17f9d
thumbs up
cataladev Jul 3, 2026
e9c80c8
waterfall fix
cataladev Jul 3, 2026
7e06fd4
allo
cataladev Jul 3, 2026
399a586
fix
cataladev Jul 3, 2026
148c672
structure of site
Adr1an04 Jul 3, 2026
657b2f9
Khix faq section (#484)
morallyearlgrey Jul 3, 2026
2fab298
sponsor water fall
Adr1an04 Jul 3, 2026
5690866
updated khix sponsor section
kwaiidev Jul 4, 2026
0919f0e
Merge remote-tracking branch 'origin/main' into khixsite
Adr1an04 Jul 5, 2026
72b84c4
khix finalized application flow
Adr1an04 Jul 6, 2026
50353ac
Merge remote-tracking branch 'origin/main' into khixsite
Adr1an04 Jul 6, 2026
0398628
kh apps and dashboard
Adr1an04 Jul 7, 2026
233ae96
speaker
cataladev Jul 7, 2026
b19ed8a
align khix faq dropdowns
kwaiidev Jul 7, 2026
ed21258
updated khix partners section
kwaiidev Jul 7, 2026
fac654f
dashboard changes
Adr1an04 Jul 7, 2026
54755c0
lore update
Adr1an04 Jul 7, 2026
80ec8a2
team cascade bg gone
cataladev Jul 7, 2026
f7003c6
gradient fix and button fixes dashboard
Adr1an04 Jul 7, 2026
7e948e3
button stuff again
Adr1an04 Jul 8, 2026
3c16bcc
404s
Adr1an04 Jul 8, 2026
72b610c
added design team plus fixed cascade
morallyearlgrey Jul 8, 2026
9015639
temp waterfall fall cascade ts
morallyearlgrey Jul 9, 2026
50ca378
navbar
cataladev Jul 9, 2026
88e84b5
mobile hero
Adr1an04 Jul 9, 2026
64100c4
new footer image and rocks
Adr1an04 Jul 9, 2026
1023c15
add speaker showcase carousel
cataladev Jul 9, 2026
6429ebe
removing matt...
cataladev Jul 9, 2026
78d02d8
emails and footer/faq
Adr1an04 Jul 9, 2026
acd4499
stuff
Adr1an04 Jul 9, 2026
a4d6c4c
navbar
Adr1an04 Jul 9, 2026
151369c
shinies and impressink
cataladev Jul 9, 2026
856e22f
waterfall
Adr1an04 Jul 9, 2026
fb714d2
polish khix sponsor mobile layout
cataladev Jul 10, 2026
ed001d4
Merge remote-tracking branch 'origin/khixsite' into khixsite
cataladev Jul 10, 2026
01a1230
remove designers cascade and smooth avatar fades
cataladev Jul 10, 2026
dbe7c8e
uh stuff i think (someone check this commit
cataladev Jul 10, 2026
d0ea538
seperator rock faq
Adr1an04 Jul 10, 2026
555ee7f
bolas
cataladev Jul 10, 2026
661c13d
rock
Adr1an04 Jul 10, 2026
60f70bc
Merge branch 'khixsite' of https://github.com/KnightHacks/forge into …
Adr1an04 Jul 10, 2026
06be4b2
faq
Adr1an04 Jul 10, 2026
d8e63ca
polish khix team cascade motion
cataladev Jul 10, 2026
9863f66
resize khix navbar on large screens
cataladev Jul 10, 2026
9e884b5
fix khix faq and footer layout
cataladev Jul 10, 2026
cbdf534
make mobile sponsor glows breathe
cataladev Jul 10, 2026
c3a630e
add khix speaker showcase section
cataladev Jul 10, 2026
b553c39
add khix tracks section and polish faq layout
kwaiidev Jul 10, 2026
2be7287
add date + location to hero; update mobile hero layout
Adr1an04 Jul 10, 2026
3ba804e
about section asset
Adr1an04 Jul 10, 2026
c3dd4a3
add glowing animation on apply deskop hover
Adr1an04 Jul 10, 2026
891a2bd
change sponsor logos to carved style
Adr1an04 Jul 10, 2026
937ff73
font
Adr1an04 Jul 10, 2026
eb81b76
merge main into khixsite
cataladev Jul 10, 2026
3c776ee
no more rocks and grass and shit, team rock resize & layunder
cataladev Jul 11, 2026
e54dbe0
sponsor no bleed
cataladev Jul 11, 2026
b2aa44c
speakers moved up
cataladev Jul 11, 2026
e612f8b
pushing
Adr1an04 Jul 11, 2026
fd15a26
add waterfall particle animations
Adr1an04 Jul 11, 2026
3abd0e0
pushing2
Adr1an04 Jul 11, 2026
60db59f
Merge branch 'khixsite' of https://github.com/KnightHacks/forge into …
Adr1an04 Jul 11, 2026
d0c247c
remove mist, fix issue with sponsor rock shadows
Adr1an04 Jul 11, 2026
e618e18
about
Adr1an04 Jul 11, 2026
b49b8eb
mobile work
Adr1an04 Jul 11, 2026
0e5955d
reorder stats
Adr1an04 Jul 11, 2026
d851879
rocks
Adr1an04 Jul 11, 2026
d7a3743
Merge branch 'khixsite' of https://github.com/KnightHacks/forge into …
Adr1an04 Jul 11, 2026
18a79f4
enrich about section
Adr1an04 Jul 11, 2026
3c8a661
spacing adjustments to about section
Adr1an04 Jul 11, 2026
26c8850
apply glowing purple style to stats
Adr1an04 Jul 11, 2026
86d78f5
fireflies
Adr1an04 Jul 11, 2026
0b5e109
center 2nd about subheader with relation to carousel
Adr1an04 Jul 11, 2026
50be75b
colors
Adr1an04 Jul 11, 2026
f62480c
Merge branch 'khixsite' of https://github.com/KnightHacks/forge into …
Adr1an04 Jul 11, 2026
768cc5d
update copy and adjust the spacing in about section in mobile
Adr1an04 Jul 11, 2026
2f63209
about length fix and ipad sponsor section
Adr1an04 Jul 11, 2026
b10fb16
Merge branch 'khixsite' of https://github.com/KnightHacks/forge into …
Adr1an04 Jul 11, 2026
c07b2c4
favicon and hero fix
Adr1an04 Jul 11, 2026
13c0908
fix links in FAQs to be hyperlinks. TODO: fix spacing issue in 1 of them
Adr1an04 Jul 11, 2026
22e0442
mobile hero fix
Adr1an04 Jul 11, 2026
f4743c6
fix spacing issue in FAQ hyperlink
Adr1an04 Jul 11, 2026
c04195e
modify sponsor and partner spacing; apparent fix for weird iOS text a…
Adr1an04 Jul 11, 2026
318cde8
teams
Adr1an04 Jul 11, 2026
1ba9def
updated footer proportions
Adr1an04 Jul 11, 2026
3db96fe
reorder sponsors and partners in alphabetical order
Adr1an04 Jul 11, 2026
68038f5
teams
Adr1an04 Jul 11, 2026
287752c
bring up team rock divider
Adr1an04 Jul 11, 2026
c4dbeb5
ipad
Adr1an04 Jul 11, 2026
ee35b4c
put FAQ header in rock divider
Adr1an04 Jul 11, 2026
992cdbc
remove placeholder text for speakers
Adr1an04 Jul 11, 2026
d7b67dc
fix issue with fireflies/wisps not showing in tracks in mobile
Adr1an04 Jul 11, 2026
f4c4c04
update speakers header to be same style as others, bring higher
Adr1an04 Jul 11, 2026
f17ae8b
waterfall cut
Adr1an04 Jul 11, 2026
dab1894
optimizing
Adr1an04 Jul 11, 2026
4ca78c9
prio loading
Adr1an04 Jul 11, 2026
88e2fe9
cdn and r2 cache
Adr1an04 Jul 11, 2026
73b44db
optimizing
Adr1an04 Jul 12, 2026
bd7a41a
Aspect ratio
Adr1an04 Jul 12, 2026
3483a66
add animated insects to the footer
Adr1an04 Jul 12, 2026
0b1cfb9
new waterfall split
Adr1an04 Jul 12, 2026
5040028
add "metallic" color on hover to sponsor rocks
Adr1an04 Jul 12, 2026
96e7b30
faq
Adr1an04 Jul 12, 2026
de3f624
Merge remote-tracking branch 'origin/main' into khixsite
Adr1an04 Jul 12, 2026
97e0a4e
clean
Adr1an04 Jul 12, 2026
eb0751c
seo
Adr1an04 Jul 12, 2026
a4a33e0
fix khix portal build prerender
Adr1an04 Jul 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ MINIO_SECRET_KEY="minioadmin"
BLADE_URL="http://localhost:3000"
NEXT_PUBLIC_BLADE_URL="http://localhost:3000"
BLOOMKNIGHTS_URL="http://localhost:3006"
KHIX_URL="http://localhost:3007"

# Passkit
WWDR_CERT_BASE64="wwdr-cert-b64"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ export function HackathonManager() {
<div className="space-y-1">
<FormLabel>Email Template Override</FormLabel>
<FormDescription>
Leave off to use the current Knight Hacks VIII email
Leave off to use the default hackathon email
templates.
</FormDescription>
</div>
Expand Down
57 changes: 57 additions & 0 deletions apps/blade/src/app/auth/khix-return/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { NextResponse } from "next/server";

import { env } from "~/env";

const DEFAULT_KHIX_RETURN_PATH = "/dashboard";
const PRODUCTION_KHIX_RETURN_ORIGIN = "https://2026.knighthacks.org";
const LOCAL_KHIX_RETURN_ORIGIN = "http://localhost:3007";

function getAllowedKhixReturnOrigins(configuredKhixOrigin: string) {
const allowedOrigins = new Set([
configuredKhixOrigin,
PRODUCTION_KHIX_RETURN_ORIGIN,
]);

if (env.NODE_ENV !== "production") {
allowedOrigins.add(LOCAL_KHIX_RETURN_ORIGIN);
}

return allowedOrigins;
}

function getKhixReturnURL(returnTo: string | null) {
const configuredKhixOrigin = new URL(env.KHIX_URL).origin;
const allowedOrigins = getAllowedKhixReturnOrigins(configuredKhixOrigin);
const defaultReturnURL = new URL(
DEFAULT_KHIX_RETURN_PATH,
configuredKhixOrigin,
);

if (!returnTo) return defaultReturnURL;

try {
const requestedReturnURL = new URL(returnTo, configuredKhixOrigin);

if (
!allowedOrigins.has(requestedReturnURL.origin) ||
!requestedReturnURL.pathname.startsWith("/")
) {
return defaultReturnURL;
}

return requestedReturnURL;
} catch {
return defaultReturnURL;
}
}

export function GET(request: Request) {
const requestUrl = new URL(request.url);
const returnTo = getKhixReturnURL(requestUrl.searchParams.get("returnTo"));

if (requestUrl.searchParams.has("authError")) {
returnTo.searchParams.set("authError", "oauth");
}

return NextResponse.redirect(returnTo);
}
6 changes: 6 additions & 0 deletions apps/blade/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ const bloomKnightsUrlSchema =
? z.string().url()
: z.string().url().default("http://localhost:3006");

const khixUrlSchema =
process.env.NODE_ENV === "production"
? z.string().url()
: z.string().url().default("http://localhost:3007");

export const env = createEnv({
extends: [authEnv, apiEnv, dbEnv],
shared: {
Expand All @@ -24,6 +29,7 @@ export const env = createEnv({
*/
server: {
BLOOMKNIGHTS_URL: bloomKnightsUrlSchema,
KHIX_URL: khixUrlSchema,
},

/**
Expand Down
14 changes: 12 additions & 2 deletions apps/khix/next.config.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { networkInterfaces } from "node:os";

const localDevOrigins = Object.values(networkInterfaces()).flatMap(
(addresses) =>
(addresses ?? [])
.filter(({ family, internal }) => family === "IPv4" && !internal)
.map(({ address }) => address),
);

/** @type {import("next").NextConfig} */
const config = {
reactStrictMode: true,
allowedDevOrigins: ["127.0.0.1", ...localDevOrigins],
images: {
formats: ["image/avif", "image/webp"],
minimumCacheTTL: 60 * 60 * 24 * 30,
unoptimized: true,
remotePatterns: [
{
protocol: "https",
hostname: "assets.knighthacks.org",
pathname: "/khix/**",
},
],
},
Expand Down
17 changes: 15 additions & 2 deletions apps/khix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,26 @@
"with-env": "dotenv -e ../../.env --"
},
"dependencies": {
"@forge/api": "workspace:*",
"@forge/auth": "workspace:*",
"@forge/consts": "workspace:*",
"@forge/db": "workspace:*",
"@forge/hackathon": "workspace:*",
"@forge/ui": "workspace:*",
"@forge/validators": "workspace:*",
"@gsap/react": "^2.1.2",
"@t3-oss/env-nextjs": "^0.13.10",
"@trpc/client": "catalog:",
"@trpc/server": "catalog:",
"framer-motion": "^12.34.3",
"gsap": "^3.14.2",
"lucide-react": "^0.575.0",
"next": "^16.2.7",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-icons": "^5.5.0"
"react-icons": "^5.5.0",
"superjson": "2.2.6",
"zod": "catalog:"
},
"devDependencies": {
"@forge/eslint-config": "workspace:*",
Expand All @@ -35,7 +49,6 @@
"eslint": "catalog:",
"prettier": "catalog:",
"tailwindcss": "catalog:",
"tw-animate-css": "^1.4.0",
"typescript": "catalog:"
},
"prettier": "@forge/prettier-config"
Expand Down
Binary file removed apps/khix/public/birds.mp3
Binary file not shown.
Binary file removed apps/khix/public/flower.png
Binary file not shown.
Binary file removed apps/khix/public/khix-gem-shard-mask.png
Binary file not shown.
41 changes: 0 additions & 41 deletions apps/khix/public/khix-logo-white.svg

This file was deleted.

32 changes: 0 additions & 32 deletions apps/khix/public/khix-sigil.svg

This file was deleted.

Binary file removed apps/khix/public/ladybug.png
Binary file not shown.
Binary file removed apps/khix/public/mushroom.png
Binary file not shown.
Binary file removed apps/khix/public/music.mp3
Binary file not shown.
77 changes: 77 additions & 0 deletions apps/khix/src/PARALLAX.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Parallax Implementation Notes

Temporary handoff for agents working on KHIX or future Forge parallax sections.
This documents the Chromium fix from Carlos's 39fc6795 commit so it can be
reused without rediscovering the same failure mode.

## What Broke

The KHIX hero parallax broke when the art stack was treated like a page
background instead of a normal hero section. The problematic shape was:

- a long or sticky scroll zone that made the hero behave like a background
- a large transformed `.art` container using `scale(...)`
- per-layer parallax values that did not account for that container scale
- unthrottled pointer writes fighting Chromium's rendering pipeline

The visible symptoms were rapid inline style churn in DevTools, unstable
Chromium parallax, and the hero reading as the entire page background instead
of a section that can scroll away.

## Carlos's Fix

Keep the hero itself as a normal section:

- `section#home` owns the hero and stays in document flow
- `.stage` is `position: relative`, not sticky, for a normal hero
- the hero is `100vh` / `100svh`; extra page scroll should come from following
sections, not from a fake hero scroll zone

Keep the artwork full-bleed inside the hero without scaling the whole .art
container:

- store the old visual scale as `--khix-art-motion-scale: 0.64`
- use a smaller art inset, currently `inset: -6.32svh -3.76vw`
- do not put `transform: scale(...)` on `.art`
- apply `--khix-art-motion-scale` inside each layer's parallax transform math

Scope motion variables to the stage and throttle writes:

- write `--khix-hero-pointer-x`, `--khix-hero-pointer-y`, and
`--khix-hero-scroll-progress` on the hero stage
- coalesce pointer movement with `requestAnimationFrame`
- only write motion values when they changed by a meaningful epsilon
- cancel pending pointer frames during cleanup and when reduced motion is
enabled

## Reusable Pattern

For future parallax components:

- make the section normal page flow first; avoid sticky or oversized scroll
zones unless the design explicitly calls for pinned storytelling
- keep the art stack visually oversized with insets, not by scaling the whole
container
- if the art needs a visual scale, put that number in a CSS variable and
multiply the pointer and scroll offsets by it
- put all layer movement on `transform: translate3d(...)` and keep depth values
as CSS vars on each layer
- use one local stage for motion vars; do not inject global `:root` motion state
for a component-specific parallax
- throttle pointer writes with `requestAnimationFrame`; throttle scroll writes
too, and skip writes when the value barely changed
- respect `prefers-reduced-motion` by resetting pointer and scroll progress to
`0` and disabling nonessential animated layers

## Verification Checklist

Before handing off a parallax change:

- the hero/section scrolls away like a normal section when content follows it
- the stage is not sticky unless pinned scroll storytelling is the requirement
- Chrome/Chromium DevTools does not show unrelated title/glow/art nodes
constantly changing inline style attributes
- pointer movement still changes layer transforms differently by depth
- scroll changes `--khix-hero-scroll-progress` without causing layout shifts
- `pnpm --filter=@forge/khix lint` and
`pnpm --filter=@forge/khix typecheck` pass for KHIX changes
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { ApplicationVisualConfig } from "./types";
import { khixApplicationBackground } from "./khix";

export const DEFAULT_APPLICATION_VISUAL = {
key: "default",
label: "Stock purple",
mode: "dynamic",
showStockEffects: true,
} satisfies ApplicationVisualConfig;

export type HackerApplicationBackgroundKey = "khix";

export const HACKER_APPLICATION_BACKGROUNDS = {
khix: khixApplicationBackground,
} satisfies Record<HackerApplicationBackgroundKey, ApplicationVisualConfig>;

function isHackerApplicationBackgroundKey(
backgroundKey: string,
): backgroundKey is HackerApplicationBackgroundKey {
return backgroundKey === "khix";
}

export function getHackerApplicationBackgroundKey(
backgroundKey?: string | null,
): HackerApplicationBackgroundKey | null {
if (!backgroundKey) return null;
if (isHackerApplicationBackgroundKey(backgroundKey)) return backgroundKey;

if (backgroundKey === "knighthacksix") return "khix";
if (backgroundKey === "knight-hacks-ix") return "khix";

return null;
}

export function getHackerApplicationBackground(
backgroundKey?: string | null,
): ApplicationVisualConfig {
const applicationBackgroundKey =
getHackerApplicationBackgroundKey(backgroundKey);

if (!applicationBackgroundKey) {
return DEFAULT_APPLICATION_VISUAL;
}

return HACKER_APPLICATION_BACKGROUNDS[applicationBackgroundKey];
}

export type { ApplicationVisualConfig, ApplicationVisualLayer } from "./types";
Loading
Loading