Skip to content

Commit b659db8

Browse files
chore: upgrade Next.js → 16.2.6, React → 19.2.6, Tailwind CSS → v4.3.0 (#74)
* chore: upgrade Next.js to 16.2.6, React to 19.2.6, headlessui to v2 Security fix: Next.js 13.x/14.x are unpatched against 13 CVEs in the May 2026 Vercel security advisory (middleware bypass, SSRF, XSS, cache poisoning). 14.x will not receive patches; minimum safe version is 15.5.18 or 16.2.6. Changes: - next: 14.1.3 -> 16.2.6 - react / react-dom: 18.2.0 -> 19.2.6 - @headlessui/react: 1.7.18 -> 2.x (peer dep of Next.js 16 / React 19) - @types/react / @types/react-dom: bumped to ^19.0.0 - eslint: 8.x -> ^9.0.0 (required by eslint-config-next@16) - eslint-config-next: 14.1.3 -> 16.2.6 Migrate modal-video.tsx to headlessui v2 API: - Replace Transition.Child with TransitionChild (named export) - Replace Dialog.Panel with DialogPanel (named export) - Remove Fragment import and as={Fragment} (v2 default is Fragment) - Wrap bare Transition.Child className content in explicit child divs tsconfig.json auto-updated by Next.js 16 first build: - moduleResolution: node -> bundler - jsx: preserve -> react-jsx Co-authored-by: Hoon Kim <hoonsubin@users.noreply.github.com> * chore: upgrade Tailwind CSS to v4.3.0 Migrate from Tailwind CSS v3 to v4 using the official @tailwindcss/upgrade tool (v4.3.0), then manually review and reconcile the output. Dependency changes: - tailwindcss: ^3.3.6 -> ^4.3.0 - @tailwindcss/forms: ^0.5.7 -> ^0.5.11 (latest, explicit v4 support) - @tailwindcss/postcss: ^4.3.0 (new; replaces tailwindcss PostCSS plugin) - autoprefixer removed (v4 handles vendor prefixes natively) - postcss-import removed (no longer needed; v4 handles @import natively) Configuration: - tailwind.config.js deleted (v4 uses CSS-first config) - postcss.config.js: tailwindcss/autoprefixer -> @tailwindcss/postcss Style migration (app/css/style.css): - @import 'tailwindcss/base|components|utilities' -> @import 'tailwindcss' - Custom theme (colors, fonts, spacing, typography) moved from tailwind.config.js into @theme {} block - @tailwindcss/forms loaded via @plugin directive - Additional stylesheets use layer() qualifier on @import - @layer utilities .rtl -> @Utility rtl Component migrations (utility class renames in Tailwind v4): - rounded-sm -> rounded-xs (Tailwind v4 scale shift) - shadow -> shadow-sm (Tailwind v4 scale shift) - z-[99999] -> z-99999 (bare arbitrary value syntax) - @screen md -> @media (width >= theme(--breakpoint-md)) Co-authored-by: Hoon Kim <hoonsubin@users.noreply.github.com> * feat: switch deployment from Netlify to GitHub Pages Configure Next.js static export and add a GitHub Actions workflow that builds the site on every push to master and deploys to GitHub Pages. next.config.js: - output: 'export' — enables next build to write static HTML/CSS/JS to ./out instead of running a Node server - trailingSlash: true — generates page/index.html so GitHub Pages can serve routes without a server-side rewrite - images.unoptimized: true — disables the Node image optimisation API (zigzag.tsx and modal-video.tsx use next/image); raw image files are served directly from the CDN app/api/hello/route.ts deleted: - Static export does not support dynamic Route Handlers; this was only a placeholder and has no consumers in the app .github/workflows/deploy.yml: - Triggers on push to master and via workflow_dispatch - Uses actions/configure-pages, upload-pages-artifact, deploy-pages (the official GitHub Pages deployment stack) - Caches Yarn packages via setup-node cache: yarn - Pages write + id-token write permissions scoped to the workflow public/CNAME: - Preserves the teamstep.io custom domain when GitHub Pages is enabled (GitHub reads this file from the published artifact root) README.md: - Replaced Netlify Status badge with GitHub Actions deploy badge - Minor cleanup (trailing newline) Co-authored-by: Hoon Kim <hoonsubin@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Hoon Kim <hoonsubin@users.noreply.github.com>
1 parent fb06a96 commit b659db8

16 files changed

Lines changed: 2426 additions & 1335 deletions

File tree

‎.github/workflows/deploy.yml‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [master]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: pages
15+
cancel-in-progress: false
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
24+
- name: Setup Node
25+
uses: actions/setup-node@v4
26+
with:
27+
node-version: '20'
28+
cache: yarn
29+
30+
- name: Setup Pages
31+
uses: actions/configure-pages@v5
32+
33+
- name: Install dependencies
34+
run: yarn install --frozen-lockfile
35+
36+
- name: Build
37+
run: yarn build
38+
39+
- name: Upload Pages artifact
40+
uses: actions/upload-pages-artifact@v3
41+
with:
42+
path: ./out
43+
44+
deploy:
45+
environment:
46+
name: github-pages
47+
url: ${{ steps.deployment.outputs.page_url }}
48+
runs-on: ubuntu-latest
49+
needs: build
50+
steps:
51+
- name: Deploy to GitHub Pages
52+
id: deployment
53+
uses: actions/deploy-pages@v4

‎README.md‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[![eslint](https://img.shields.io/badge/eslint-enabled-green.svg)](https://eslint.org/)
44
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
5-
[![Netlify Status](https://api.netlify.com/api/v1/badges/b71bbe1a-3dfa-4b39-945b-bb15bb872b87/deploy-status)](https://app.netlify.com/sites/teamstep-homepage/deploys)
5+
[![Deploy](https://github.com/TeamSTEP/teamstep.io/actions/workflows/deploy.yml/badge.svg)](https://github.com/TeamSTEP/teamstep.io/actions/workflows/deploy.yml)
66

77
This is the homepage source code for Team STEP.
88

@@ -14,5 +14,4 @@ This page is based on the [Open React Template](https://github.com/cruip/open-re
1414
yarn # install dependencies
1515

1616
yarn dev # start serving the project on a development server
17-
1817
```

‎app/api/hello/route.ts‎

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎app/css/additional-styles/utility-patterns.css‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
@apply text-2xl font-bold leading-snug tracking-tight;
1616
}
1717

18-
@screen md {
18+
@media (width >= theme(--breakpoint-md)) {
1919
.h1 {
2020
@apply text-5xl;
2121
}
@@ -28,7 +28,7 @@
2828
/* Buttons */
2929
.btn,
3030
.btn-sm {
31-
@apply font-medium inline-flex items-center justify-center border border-transparent rounded-sm leading-snug transition duration-150 ease-in-out;
31+
@apply font-medium inline-flex items-center justify-center border border-transparent rounded-xs leading-snug transition duration-150 ease-in-out;
3232
}
3333

3434
.btn {
@@ -54,7 +54,7 @@
5454
.form-multiselect,
5555
.form-select,
5656
.form-checkbox {
57-
@apply rounded-sm;
57+
@apply rounded-xs;
5858
}
5959

6060
.form-input,

‎app/css/style.css‎

Lines changed: 91 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,99 @@
1-
@import 'tailwindcss/base';
2-
@import 'tailwindcss/components';
1+
@import 'tailwindcss';
32

43
/* Additional styles */
5-
@import 'additional-styles/utility-patterns.css';
6-
@import 'additional-styles/range-slider.css';
7-
@import 'additional-styles/toggle-switch.css';
8-
@import 'additional-styles/theme.css';
4+
@import './additional-styles/utility-patterns.css' layer(components);
5+
@import './additional-styles/range-slider.css' layer(components);
6+
@import './additional-styles/toggle-switch.css' layer(components);
7+
@import './additional-styles/theme.css' layer(components);
98

10-
@import 'tailwindcss/utilities';
9+
@plugin '@tailwindcss/forms';
10+
11+
@theme {
12+
--color-gray-100: #ebf1f5;
13+
--color-gray-200: #d9e3ea;
14+
--color-gray-300: #c5d2dc;
15+
--color-gray-400: #9ba9b4;
16+
--color-gray-500: #707d86;
17+
--color-gray-600: #55595f;
18+
--color-gray-700: #33363a;
19+
--color-gray-800: #25282c;
20+
--color-gray-900: #151719;
21+
22+
--color-purple-100: #f4f4ff;
23+
--color-purple-200: #e2e1ff;
24+
--color-purple-300: #cbccff;
25+
--color-purple-400: #ababff;
26+
--color-purple-500: #8d8dff;
27+
--color-purple-600: #8591c9;
28+
--color-purple-700: #7274a2;
29+
--color-purple-800: #4f476d;
30+
--color-purple-900: #231630;
31+
32+
--color-orange-100: #fde0d8;
33+
--color-orange-200: #fab29e;
34+
--color-orange-300: #f89377;
35+
--color-orange-400: #f78464;
36+
--color-orange-500: #f46036;
37+
--color-orange-600: #ef481a;
38+
--color-orange-700: #e93c0c;
39+
--color-orange-800: #ae2d09;
40+
--color-orange-900: #270a02;
41+
42+
--spacing-9\/16: 56.25%;
43+
--spacing-3\/4: 75%;
44+
--spacing-1\/1: 100%;
45+
46+
--font-jura: var(--font-jura), sans-serif;
47+
--font-trispace: var(--font-trispace), sans-serif;
48+
--font-inter: var(--font-inter), sans-serif;
49+
--font-architects-daughter: var(--font-architects-daughter), sans-serif;
50+
51+
--text-xs: 0.75rem;
52+
--text-sm: 0.875rem;
53+
--text-base: 1rem;
54+
--text-lg: 1.125rem;
55+
--text-xl: 1.25rem;
56+
--text-2xl: 1.5rem;
57+
--text-3xl: 2rem;
58+
--text-4xl: 2.5rem;
59+
--text-5xl: 3.25rem;
60+
--text-6xl: 4rem;
61+
62+
--inset-full: 100%;
63+
64+
--tracking-tighter: -0.02em;
65+
--tracking-tight: -0.01em;
66+
--tracking-normal: 0;
67+
--tracking-wide: 0.01em;
68+
--tracking-wider: 0.02em;
69+
--tracking-widest: 0.4em;
70+
71+
--min-width-10: 2.5rem;
72+
73+
--scale-98: 0.98;
74+
}
75+
76+
/*
77+
The default border color has changed to `currentcolor` in Tailwind CSS v4,
78+
so we've added these compatibility styles to make sure everything still
79+
looks the same as it did with Tailwind CSS v3.
80+
81+
If we ever want to remove these styles, we need to add an explicit border
82+
color utility to any element that depends on these defaults.
83+
*/
84+
@layer base {
85+
*,
86+
::after,
87+
::before,
88+
::backdrop,
89+
::file-selector-button {
90+
border-color: var(--color-gray-200, currentcolor);
91+
}
92+
}
1193

1294
/* Additional Tailwind directives: https://tailwindcss.com/docs/functions-and-directives/#responsive */
13-
@layer utilities {
14-
.rtl {
15-
direction: rtl;
16-
}
95+
@utility rtl {
96+
direction: rtl;
1797
}
1898

1999
/* See Alpine.js: https://github.com/alpinejs/alpine#x-cloak */

‎components/banner.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default function Banner() {
99
<>
1010
{bannerOpen && (
1111
<div className="fixed bottom-0 right-0 w-full md:bottom-8 md:right-12 md:w-auto z-50">
12-
<div className="bg-slate-800 text-slate-50 text-sm p-3 md:rounded shadow-lg flex justify-between">
12+
<div className="bg-slate-800 text-slate-50 text-sm p-3 md:rounded-sm shadow-lg flex justify-between">
1313
<div className="text-slate-500 inline-flex">
1414
<a
1515
className="font-medium hover:underline text-slate-50"

‎components/modal-video.tsx‎

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use client'
22

3-
import { useState, useRef, Fragment } from 'react'
3+
import { useState, useRef } from 'react'
44
import type { StaticImageData } from 'next/image'
5-
import { Dialog, Transition } from '@headlessui/react'
5+
import { Dialog, DialogPanel, Transition, TransitionChild } from '@headlessui/react'
66
import Image from 'next/image'
77

88
interface ModalVideoProps {
@@ -50,46 +50,47 @@ export default function ModalVideo({
5050
</div>
5151
{/* End: Video thumbnail */}
5252

53-
<Transition show={modalOpen} as={Fragment} afterEnter={() => videoRef.current?.play()}>
54-
<Dialog initialFocus={videoRef} onClose={() => setModalOpen(false)}>
53+
<Transition show={modalOpen} afterEnter={() => videoRef.current?.play()}>
54+
<Dialog onClose={() => setModalOpen(false)}>
5555

5656
{/* Modal backdrop */}
57-
<Transition.Child
58-
className="fixed inset-0 z-[99999] bg-black bg-opacity-75 transition-opacity"
57+
<TransitionChild
5958
enter="transition ease-out duration-200"
6059
enterFrom="opacity-0"
6160
enterTo="opacity-100"
6261
leave="transition ease-out duration-100"
6362
leaveFrom="opacity-100"
6463
leaveTo="opacity-0"
65-
aria-hidden="true"
66-
/>
64+
>
65+
<div className="fixed inset-0 z-99999 bg-black bg-opacity-75 transition-opacity" aria-hidden="true" />
66+
</TransitionChild>
6767
{/* End: Modal backdrop */}
6868

6969
{/* Modal dialog */}
70-
<Transition.Child
71-
className="fixed inset-0 z-[99999] overflow-hidden flex items-center justify-center transform px-4 sm:px-6"
70+
<TransitionChild
7271
enter="transition ease-out duration-200"
7372
enterFrom="opacity-0 scale-95"
7473
enterTo="opacity-100 scale-100"
75-
leave="ttransition ease-out duration-200"
76-
leaveFrom="oopacity-100 scale-100"
74+
leave="transition ease-out duration-200"
75+
leaveFrom="opacity-100 scale-100"
7776
leaveTo="opacity-0 scale-95"
7877
>
79-
<div className="max-w-6xl mx-auto h-full flex items-center">
80-
<Dialog.Panel className="w-full max-h-full aspect-video bg-black overflow-hidden">
81-
<video ref={videoRef} width={videoWidth} height={videoHeight} loop controls>
82-
<source src={video} type="video/mp4" />
83-
Your browser does not support the video tag.
84-
</video>
85-
</Dialog.Panel>
78+
<div className="fixed inset-0 z-99999 overflow-hidden flex items-center justify-center transform px-4 sm:px-6">
79+
<div className="max-w-6xl mx-auto h-full flex items-center">
80+
<DialogPanel className="w-full max-h-full aspect-video bg-black overflow-hidden">
81+
<video ref={videoRef} width={videoWidth} height={videoHeight} loop controls>
82+
<source src={video} type="video/mp4" />
83+
Your browser does not support the video tag.
84+
</video>
85+
</DialogPanel>
86+
</div>
8687
</div>
87-
</Transition.Child>
88+
</TransitionChild>
8889
{/* End: Modal dialog */}
8990

9091
</Dialog>
9192
</Transition>
9293

9394
</div>
9495
)
95-
}
96+
}

‎components/newsletter.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,18 @@ export default function Newsletter() {
6060
<div className="flex flex-col sm:flex-row justify-center max-w-xs mx-auto sm:max-w-md lg:max-w-none">
6161
{/* <input
6262
type="email"
63-
className="w-full appearance-none bg-purple-700 border border-purple-500 focus:border-purple-300 rounded-sm px-4 py-3 mb-2 sm:mb-0 sm:mr-2 text-white placeholder-purple-400"
63+
className="w-full appearance-none bg-purple-700 border border-purple-500 focus:border-purple-300 rounded-xs px-4 py-3 mb-2 sm:mb-0 sm:mr-2 text-white placeholder-purple-400"
6464
placeholder="Your best email…"
6565
aria-label="Your best email…"
6666
/> */}
6767
<a
68-
className="rounded-sm px-4 py-3 mb-2 sm:mb-0 sm:mr-2 text-purple-800 bg-purple-100 hover:bg-white shadow"
68+
className="rounded-xs px-4 py-3 mb-2 sm:mb-0 sm:mr-2 text-purple-800 bg-purple-100 hover:bg-white shadow-sm"
6969
href="https://discord.gg/XCGSmhGsUQ"
7070
>
7171
Discord
7272
</a>
7373
<a
74-
className="rounded-sm px-4 py-3 mb-2 sm:mb-0 sm:mr-2 text-purple-800 bg-purple-100 hover:bg-white shadow"
74+
className="rounded-xs px-4 py-3 mb-2 sm:mb-0 sm:mr-2 text-purple-800 bg-purple-100 hover:bg-white shadow-sm"
7575
href="https://twitter.com/teamstepgames"
7676
>
7777
Twitter

‎components/ui/mobile-menu.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export default function MobileMenu() {
6868
<li>
6969
<Link
7070
href="/signup"
71-
className="font-medium w-full inline-flex items-center justify-center border border-transparent px-4 py-2 my-2 rounded-sm text-white bg-purple-600 hover:bg-purple-700 transition duration-150 ease-in-out" onClick={() => setMobileNavOpen(false)}
71+
className="font-medium w-full inline-flex items-center justify-center border border-transparent px-4 py-2 my-2 rounded-xs text-white bg-purple-600 hover:bg-purple-700 transition duration-150 ease-in-out" onClick={() => setMobileNavOpen(false)}
7272
>
7373
Sign up
7474
</Link>

‎next.config.js‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
/** @type {import('next').NextConfig} */
2-
const nextConfig = {}
2+
const nextConfig = {
3+
output: 'export',
4+
trailingSlash: true,
5+
images: {
6+
unoptimized: true,
7+
},
8+
}
39

410
module.exports = nextConfig

0 commit comments

Comments
 (0)