feat: no more vercel, next. now vite and nix
14
.env.example
|
|
@ -1,14 +0,0 @@
|
||||||
# Since the ".env" file is gitignored, you can use the ".env.example" file to
|
|
||||||
# build a new ".env" file when you clone the repo. Keep this file up-to-date
|
|
||||||
# when you add new variables to `.env`.
|
|
||||||
|
|
||||||
# This file will be committed to version control, so make sure not to have any
|
|
||||||
# secrets in it. If you are cloning this repo, create a copy of this file named
|
|
||||||
# ".env" and populate it with your secrets.
|
|
||||||
|
|
||||||
# When adding additional environment variables, the schema in "/src/env.js"
|
|
||||||
# should be updated accordingly.
|
|
||||||
|
|
||||||
# Prisma
|
|
||||||
# https://www.prisma.io/docs/reference/database-reference/connection-urls#env
|
|
||||||
DATABASE_URL="postgresql://postgres:password@localhost:5432/website"
|
|
||||||
25
.gitignore
vendored
|
|
@ -1,25 +1,11 @@
|
||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
/.pnp
|
|
||||||
.pnp.js
|
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
# database
|
# vite
|
||||||
/prisma/db.sqlite
|
/dist
|
||||||
/prisma/db.sqlite-journal
|
|
||||||
db.sqlite
|
|
||||||
|
|
||||||
# next.js
|
|
||||||
/.next/
|
|
||||||
/out/
|
|
||||||
next-env.d.ts
|
|
||||||
|
|
||||||
# production
|
|
||||||
/build
|
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
@ -31,14 +17,10 @@ yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
.pnpm-debug.log*
|
.pnpm-debug.log*
|
||||||
|
|
||||||
# local env files
|
# env files
|
||||||
# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables
|
|
||||||
.env
|
.env
|
||||||
.env*.local
|
.env*.local
|
||||||
|
|
||||||
# vercel
|
|
||||||
.vercel
|
|
||||||
|
|
||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
|
@ -46,4 +28,3 @@ yarn-error.log*
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
/.direnv
|
/.direnv
|
||||||
/generated
|
|
||||||
|
|
@ -1,13 +1,8 @@
|
||||||
import { FlatCompat } from "@eslint/eslintrc";
|
|
||||||
import tseslint from 'typescript-eslint';
|
import tseslint from 'typescript-eslint';
|
||||||
|
|
||||||
const compat = new FlatCompat({
|
|
||||||
baseDirectory: import.meta.dirname,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default tseslint.config(
|
export default tseslint.config(
|
||||||
{
|
{
|
||||||
ignores: ['.next', 'cgol/pkg/**/*', 'next-env.d.ts']
|
ignores: ['dist', 'cgol/pkg/**/*']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['**/*.ts', '**/*.tsx'],
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
|
|
||||||
12
flake.lock
generated
|
|
@ -20,11 +20,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771369470,
|
"lastModified": 1772542754,
|
||||||
"narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=",
|
"narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "0182a361324364ae3f436a63005877674cf45efb",
|
"rev": "8c809a146a140c5c8806f13399592dbcb1bb5dc4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -62,11 +62,11 @@
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771384185,
|
"lastModified": 1772679930,
|
||||||
"narHash": "sha256-KvmjUeA7uODwzbcQoN/B8DCZIbhT/Q/uErF1BBMcYnw=",
|
"narHash": "sha256-FxYmdacqrdDVeE9QqZKTIpNLjv2B8GSKssgwlZuTR98=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "23dd7fa91602a68bd04847ac41bc10af1e6e2fd2",
|
"rev": "9b741db17141331fdb26270a1b66b81be8be9edd",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
75
flake.nix
|
|
@ -1,63 +1,44 @@
|
||||||
{
|
{
|
||||||
description = "CTF Jet development environment (Bun)";
|
description = "Jet Pham's personal website";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, rust-overlay, flake-utils }:
|
outputs = { self, nixpkgs, rust-overlay, flake-utils }:
|
||||||
flake-utils.lib.eachDefaultSystem (system:
|
(flake-utils.lib.eachDefaultSystem (system:
|
||||||
let
|
let
|
||||||
overlays = [ (import rust-overlay) ];
|
overlays = [ (import rust-overlay) ];
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs { inherit system overlays; };
|
||||||
inherit system overlays;
|
rustToolchain = pkgs.rust-bin.selectLatestNightlyWith (toolchain:
|
||||||
};
|
toolchain.default.override {
|
||||||
|
|
||||||
bun = pkgs.bun;
|
|
||||||
|
|
||||||
# Prisma engines for NixOS
|
|
||||||
prismaEngines = pkgs.prisma-engines;
|
|
||||||
|
|
||||||
devTools = with pkgs; [
|
|
||||||
git
|
|
||||||
postgresql
|
|
||||||
curl
|
|
||||||
wget
|
|
||||||
typescript-language-server
|
|
||||||
pkg-config
|
|
||||||
wasm-pack
|
|
||||||
binaryen
|
|
||||||
(rust-bin.selectLatestNightlyWith (toolchain: toolchain.default.override {
|
|
||||||
extensions = [ "rust-src" ];
|
extensions = [ "rust-src" ];
|
||||||
targets = [ "wasm32-unknown-unknown" ];
|
targets = [ "wasm32-unknown-unknown" ];
|
||||||
}))
|
});
|
||||||
];
|
website = pkgs.stdenv.mkDerivation {
|
||||||
|
pname = "jet-website";
|
||||||
|
version = "0.1.0";
|
||||||
|
src = pkgs.lib.cleanSource ./.;
|
||||||
|
nativeBuildInputs = [ pkgs.nodejs rustToolchain pkgs.wasm-pack pkgs.binaryen pkgs.pkg-config ];
|
||||||
|
buildPhase = ''
|
||||||
|
export HOME=$TMPDIR
|
||||||
|
cd cgol && wasm-pack build --release --target web && cd ..
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r dist/* $out/
|
||||||
|
'';
|
||||||
|
};
|
||||||
in {
|
in {
|
||||||
|
packages = { default = website; };
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
buildInputs = [
|
buildInputs = with pkgs; [
|
||||||
bun
|
nodejs git curl typescript-language-server
|
||||||
prismaEngines
|
pkg-config wasm-pack binaryen rustToolchain
|
||||||
] ++ devTools;
|
];
|
||||||
|
|
||||||
NIXPKGS_ALLOW_UNFREE = "1";
|
|
||||||
|
|
||||||
PRISMA_QUERY_ENGINE_BINARY = "${prismaEngines}/bin/query-engine";
|
|
||||||
PRISMA_SCHEMA_ENGINE_BINARY = "${prismaEngines}/bin/schema-engine";
|
|
||||||
PRISMA_INTROSPECTION_ENGINE_BINARY = "${prismaEngines}/bin/introspection-engine";
|
|
||||||
PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING = "1";
|
|
||||||
};
|
|
||||||
|
|
||||||
packages = {
|
|
||||||
inherit bun prismaEngines;
|
|
||||||
|
|
||||||
default = pkgs.symlinkJoin {
|
|
||||||
name = "ctfjet-dev-bun";
|
|
||||||
paths = [ bun prismaEngines ];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
index.html
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Jet Pham" />
|
||||||
|
<title>Jet Pham - Software Extremist</title>
|
||||||
|
<meta name="description" content="Jet Pham's personal website" />
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<link rel="apple-touch-icon" href="/apple-icon.png" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
37
install.sh
|
|
@ -1,37 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# fix home issues
|
|
||||||
export HOME=/root
|
|
||||||
|
|
||||||
# Install Rustup
|
|
||||||
if ! command -v rustup
|
|
||||||
then
|
|
||||||
echo "Installing Rustup..."
|
|
||||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y -t wasm32-unknown-unknown --profile minimal
|
|
||||||
source "$HOME/.cargo/env"
|
|
||||||
else
|
|
||||||
echo "Rustup already installed."
|
|
||||||
rustup target add wasm32-unknown-unknown
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install wasm-pack
|
|
||||||
if ! command -v wasm-pack
|
|
||||||
then
|
|
||||||
echo "Installing wasm-pack..."
|
|
||||||
curl https://drager.github.io/wasm-pack/installer/init.sh -sSf | sh
|
|
||||||
echo "wasm-pack installation complete."
|
|
||||||
else
|
|
||||||
echo "wasm-pack already installed."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build cgol WASM package
|
|
||||||
echo "Building cgol WASM package..."
|
|
||||||
cd cgol
|
|
||||||
wasm-pack build --release --target web
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
# Install Next.js dependencies with bun
|
|
||||||
echo "Installing Next.js dependencies with bun..."
|
|
||||||
bun install
|
|
||||||
|
|
||||||
100
next.config.js
|
|
@ -1,100 +0,0 @@
|
||||||
/**
|
|
||||||
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
|
|
||||||
* for Docker builds.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/** @type {import("next").NextConfig} */
|
|
||||||
const config = {
|
|
||||||
webpack: (config, { isServer }) => {
|
|
||||||
config.module.rules.push({
|
|
||||||
test: /\.txt$/,
|
|
||||||
type: "asset/source",
|
|
||||||
});
|
|
||||||
|
|
||||||
config.experiments = {
|
|
||||||
...config.experiments,
|
|
||||||
asyncWebAssembly: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
config.module.rules.push({
|
|
||||||
test: /\.wasm$/,
|
|
||||||
type: "asset/resource",
|
|
||||||
generator: {
|
|
||||||
filename: "static/wasm/[name].[hash][ext]",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ensure WASM files are properly handled
|
|
||||||
config.resolve.fallback = {
|
|
||||||
...config.resolve.fallback,
|
|
||||||
fs: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ensure WASM files are properly served
|
|
||||||
config.output.webassemblyModuleFilename = "static/wasm/[modulehash].wasm";
|
|
||||||
|
|
||||||
return config;
|
|
||||||
},
|
|
||||||
turbopack: {
|
|
||||||
rules: {
|
|
||||||
"*.txt": {
|
|
||||||
loaders: ["raw-loader"],
|
|
||||||
as: "*.js",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
productionBrowserSourceMaps: false,
|
|
||||||
// Redirect /_not-found to /
|
|
||||||
async redirects() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
source: '/_not-found',
|
|
||||||
destination: '/',
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
// Ensure static files are properly served
|
|
||||||
async headers() {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
source: '/:path*',
|
|
||||||
headers: [
|
|
||||||
{
|
|
||||||
key: 'Cross-Origin-Opener-Policy',
|
|
||||||
value: 'same-origin',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Cross-Origin-Resource-Policy',
|
|
||||||
value: 'cross-origin',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: '/_next/static/:path*',
|
|
||||||
headers: [
|
|
||||||
{
|
|
||||||
key: 'Cross-Origin-Resource-Policy',
|
|
||||||
value: 'cross-origin',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
source: '/_next/static/wasm/:path*',
|
|
||||||
headers: [
|
|
||||||
{
|
|
||||||
key: 'Cross-Origin-Resource-Policy',
|
|
||||||
value: 'cross-origin',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Content-Type',
|
|
||||||
value: 'application/wasm',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
||||||
3970
package-lock.json
generated
Normal file
42
package.json
|
|
@ -4,52 +4,40 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "next build",
|
"build": "vite build",
|
||||||
"build:wasm": "cd cgol && wasm-pack build --release --target web",
|
"build:wasm": "cd cgol && wasm-pack build --release --target web",
|
||||||
"check": "bun run lint && tsc --noEmit",
|
"check": "npm run lint && tsc --noEmit",
|
||||||
"dev": "next dev --turbo",
|
"dev": "vite",
|
||||||
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
||||||
"format:write": "prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
"format:write": "prettier --write \"**/*.{ts,tsx,js,jsx,mdx}\" --cache",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"lint:fix": "next lint --fix",
|
"lint:fix": "eslint . --fix",
|
||||||
"preview": "next build && next start",
|
"preview": "vite preview",
|
||||||
"start": "next start",
|
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tanstack/react-query": "^5.90.21",
|
|
||||||
"anser": "^2.3.5",
|
"anser": "^2.3.5",
|
||||||
"cgol": "file:./cgol/pkg",
|
"cgol": "file:./cgol/pkg",
|
||||||
"escape-carriage": "^1.3.1",
|
"escape-carriage": "^1.3.1",
|
||||||
"next": "^16.1.6",
|
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4"
|
||||||
"server-only": "^0.0.1",
|
|
||||||
"superjson": "^2.2.6"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.3.3",
|
"@tailwindcss/vite": "^4.2.1",
|
||||||
"@next/eslint-plugin-next": "^16.1.6",
|
"@types/node": "^25.3.3",
|
||||||
"@tailwindcss/postcss": "^4.2.0",
|
|
||||||
"@types/node": "^25.3.0",
|
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"eslint": "^9",
|
"@vitejs/plugin-react": "^5.1.4",
|
||||||
"eslint-config-next": "^16.1.6",
|
"eslint": "^10",
|
||||||
"postcss": "^8.5.6",
|
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.1",
|
||||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||||
"raw-loader": "^4.0.2",
|
"tailwindcss": "^4.2.1",
|
||||||
"react-doctor": "^0.0.21",
|
|
||||||
"tailwindcss": "^4.2.0",
|
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"typescript-eslint": "^8.56.0",
|
"typescript-eslint": "^8.56.1",
|
||||||
"webpack": "^5.105.2"
|
"vite": "^7.3.1",
|
||||||
|
"vite-plugin-top-level-await": "^1.6.0",
|
||||||
|
"vite-plugin-wasm": "^3.5.0"
|
||||||
},
|
},
|
||||||
"ct3aMetadata": {
|
|
||||||
"initVersion": "7.40.0"
|
|
||||||
},
|
|
||||||
"overrides": {},
|
|
||||||
"knip": {
|
"knip": {
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"cgol/pkg/**"
|
"cgol/pkg/**"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
export default {
|
|
||||||
plugins: {
|
|
||||||
"@tailwindcss/postcss": {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 979 KiB After Width: | Height: | Size: 979 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
|
@ -1,17 +1,10 @@
|
||||||
import Link from "next/link";
|
import { BorderedBox } from "~/components/bordered-box";
|
||||||
import Image from "next/image";
|
import { FrostedBox } from "~/components/frosted-box";
|
||||||
import { BorderedBox } from "./_components/bordered-box";
|
import Header from "~/components/header";
|
||||||
import { FrostedBox } from "./_components/frosted-box";
|
import { CgolCanvas } from "~/components/cgol-canvas";
|
||||||
import Header from "./_components/header";
|
import Jet from "~/assets/Jet.txt?raw";
|
||||||
import { CgolCanvas } from "./_components/cgol-canvas";
|
|
||||||
import FirstName from "~/assets/Jet.txt";
|
|
||||||
|
|
||||||
export const metadata = {
|
export default function App() {
|
||||||
title: "Jet Pham - Software Extremist",
|
|
||||||
description: "Personal website of Jet Pham, a software extremist.",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function Home() {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CgolCanvas />
|
<CgolCanvas />
|
||||||
|
|
@ -20,58 +13,57 @@ export default async function Home() {
|
||||||
<FrostedBox className="my-[2ch] w-full max-w-[66.666667%] min-w-fit md:mt-[4ch]">
|
<FrostedBox className="my-[2ch] w-full max-w-[66.666667%] min-w-fit md:mt-[4ch]">
|
||||||
<div className="flex flex-col items-center justify-center gap-[2ch] md:flex-row">
|
<div className="flex flex-col items-center justify-center gap-[2ch] md:flex-row">
|
||||||
<div className="order-1 flex flex-col items-center md:order-2">
|
<div className="order-1 flex flex-col items-center md:order-2">
|
||||||
<Header content={FirstName} />
|
<Header content={Jet} />
|
||||||
<div className="mt-[2ch]">Software Extremist</div>
|
<div className="mt-[2ch]">Software Extremist</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="order-2 shrink-0 md:order-1">
|
<div className="order-2 shrink-0 md:order-1">
|
||||||
<Image
|
<img
|
||||||
src="/jet.svg"
|
src="/jet.svg"
|
||||||
alt="Jet"
|
alt="Jet"
|
||||||
width={250}
|
width={250}
|
||||||
height={250}
|
height={250}
|
||||||
className="aspect-square w-full max-w-[250px] object-cover md:h-[263px] md:w-[175px] md:max-w-none"
|
className="aspect-square w-full max-w-[250px] object-cover md:h-[263px] md:w-[175px] md:max-w-none"
|
||||||
priority
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<BorderedBox label="Contact" className="mt-[2ch]">
|
<BorderedBox label="Contact" className="mt-[2ch]">
|
||||||
<Link href="mailto:jet@extremist.software">
|
<a href="mailto:jet@extremist.software">
|
||||||
jet@extremist.software
|
jet@extremist.software
|
||||||
</Link>
|
</a>
|
||||||
</BorderedBox>
|
</BorderedBox>
|
||||||
<BorderedBox label="Links">
|
<BorderedBox label="Links">
|
||||||
<ol>
|
<ol>
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<a
|
||||||
href="https://git.extremist.software"
|
href="https://git.extremist.software"
|
||||||
className="inline-flex items-center"
|
className="inline-flex items-center"
|
||||||
>
|
>
|
||||||
Forgejo
|
Forgejo
|
||||||
</Link>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<a
|
||||||
href="https://github.com/jetpham"
|
href="https://github.com/jetpham"
|
||||||
className="inline-flex items-center"
|
className="inline-flex items-center"
|
||||||
>
|
>
|
||||||
GitHub
|
GitHub
|
||||||
</Link>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<a
|
||||||
href="https://x.com/jetpham5"
|
href="https://x.com/jetpham5"
|
||||||
className="inline-flex items-center"
|
className="inline-flex items-center"
|
||||||
>
|
>
|
||||||
X
|
X
|
||||||
</Link>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Link
|
<a
|
||||||
href="https://bsky.app/profile/jetpham.com"
|
href="https://bsky.app/profile/jetpham.com"
|
||||||
className="inline-flex items-center"
|
className="inline-flex items-center"
|
||||||
>
|
>
|
||||||
Bluesky
|
Bluesky
|
||||||
</Link>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</BorderedBox>
|
</BorderedBox>
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import "~/styles/globals.css";
|
|
||||||
|
|
||||||
import { type Metadata, type Viewport } from "next";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: "Jet Pham",
|
|
||||||
description: "Jet Pham's personal website",
|
|
||||||
appleWebApp: {
|
|
||||||
title: "Jet Pham",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const viewport: Viewport = {
|
|
||||||
width: "device-width",
|
|
||||||
initialScale: 1,
|
|
||||||
themeColor: "#000000",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function RootLayout({
|
|
||||||
children,
|
|
||||||
}: Readonly<{ children: React.ReactNode }>) {
|
|
||||||
return (
|
|
||||||
<html lang="en">
|
|
||||||
<body>
|
|
||||||
{children}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
import { useEffect, useRef, useCallback } from "react";
|
import { useEffect, useRef, useCallback } from "react";
|
||||||
|
|
||||||
export function CgolCanvas() {
|
export function CgolCanvas() {
|
||||||
7
src/global.d.ts
vendored
|
|
@ -1,10 +1,11 @@
|
||||||
declare module "*.txt" {
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
declare module "*.txt?raw" {
|
||||||
const content: string;
|
const content: string;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "*.utf8ans" {
|
declare module "*.utf8ans?raw" {
|
||||||
const content: string;
|
const content: string;
|
||||||
export default content;
|
export default content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
src/main.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { StrictMode } from "react";
|
||||||
|
import { createRoot } from "react-dom/client";
|
||||||
|
import "~/styles/globals.css";
|
||||||
|
import App from "./App";
|
||||||
|
|
||||||
|
createRoot(document.getElementById("root")!).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>,
|
||||||
|
);
|
||||||
|
|
@ -23,11 +23,6 @@
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "Bundler",
|
"moduleResolution": "Bundler",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"name": "next"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
/* Path Aliases */
|
/* Path Aliases */
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
|
|
@ -38,17 +33,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"next-env.d.ts",
|
|
||||||
"**/*.ts",
|
"**/*.ts",
|
||||||
"**/*.tsx",
|
"**/*.tsx",
|
||||||
"**/*.cjs",
|
"**/*.cjs",
|
||||||
"**/*.js",
|
"**/*.js",
|
||||||
".next/types/**/*.ts",
|
"vite.config.ts"
|
||||||
".next/dev/types/**/*.ts"
|
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"generated",
|
"dist",
|
||||||
"cgol/pkg"
|
"cgol/pkg"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
vite.config.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { defineConfig } from "vite";
|
||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
import wasm from "vite-plugin-wasm";
|
||||||
|
import topLevelAwait from "vite-plugin-top-level-await";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react(), tailwindcss(), wasm(), topLevelAwait()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"~": "/src",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
headers: {
|
||||||
|
"Cross-Origin-Opener-Policy": "same-origin",
|
||||||
|
"Cross-Origin-Embedder-Policy": "require-corp",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
target: "esnext",
|
||||||
|
},
|
||||||
|
});
|
||||||