summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhongheng Liu <z.liu@outlook.com.gr>2025-02-25 15:50:48 +0200
committerZhongheng Liu <z.liu@outlook.com.gr>2025-02-25 15:50:48 +0200
commit92c93fb15fdae7db0634ad006728ffad63d169d0 (patch)
tree3c9f65638b73956053caf5b33a958414688460df
parenta12f8c73cb08a16f5a75b317e94a4f476999da36 (diff)
downloadstvnliu.gitlab.io-92c93fb15fdae7db0634ad006728ffad63d169d0.tar.gz
stvnliu.gitlab.io-92c93fb15fdae7db0634ad006728ffad63d169d0.tar.bz2
stvnliu.gitlab.io-92c93fb15fdae7db0634ad006728ffad63d169d0.zip
feat: refreshed design. more dark.
-rw-r--r--app/package-lock.json222
-rw-r--r--app/package.json3
-rw-r--r--app/public/assets/bg.pngbin0 -> 2390736 bytes
-rw-r--r--app/public/index.html64
-rw-r--r--app/src/App.css44
-rw-r--r--app/src/App.tsx111
-rw-r--r--app/src/Content.css63
-rw-r--r--app/src/Content.tsx54
-rw-r--r--app/src/HomepageNavbar.tsx39
-rw-r--r--app/src/assets/bg.pngbin0 -> 2390736 bytes
-rw-r--r--app/src/assets/wip.jpgbin0 -> 39901 bytes
-rw-r--r--public/index.html47
12 files changed, 547 insertions, 100 deletions
diff --git a/app/package-lock.json b/app/package-lock.json
index d05e337..5d6e5ec 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -16,7 +16,10 @@
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"bootstrap": "^5.3.3",
+ "holder": "^0.0.0",
+ "holderjs": "^2.9.9",
"react": "^18.3.1",
+ "react-bootstrap": "^2.10.9",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
@@ -1966,9 +1969,9 @@
"integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA=="
},
"node_modules/@babel/runtime": {
- "version": "7.24.5",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.5.tgz",
- "integrity": "sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz",
+ "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -3301,12 +3304,75 @@
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
- "peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
+ "node_modules/@react-aria/ssr": {
+ "version": "3.9.7",
+ "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.7.tgz",
+ "integrity": "sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "engines": {
+ "node": ">= 12"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@restart/hooks": {
+ "version": "0.4.16",
+ "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz",
+ "integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==",
+ "dependencies": {
+ "dequal": "^2.0.3"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@restart/ui": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.9.4.tgz",
+ "integrity": "sha512-N4C7haUc3vn4LTwVUPlkJN8Ach/+yIMvRuTVIhjilNHqegY60SGLrzud6errOMNJwSnmYFnt1J0H/k8FE3A4KA==",
+ "dependencies": {
+ "@babel/runtime": "^7.26.0",
+ "@popperjs/core": "^2.11.8",
+ "@react-aria/ssr": "^3.5.0",
+ "@restart/hooks": "^0.5.0",
+ "@types/warning": "^3.0.3",
+ "dequal": "^2.0.3",
+ "dom-helpers": "^5.2.0",
+ "uncontrollable": "^8.0.4",
+ "warning": "^4.0.3"
+ },
+ "peerDependencies": {
+ "react": ">=16.14.0",
+ "react-dom": ">=16.14.0"
+ }
+ },
+ "node_modules/@restart/ui/node_modules/@restart/hooks": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.5.1.tgz",
+ "integrity": "sha512-EMoH04NHS1pbn07iLTjIjgttuqb7qu4+/EyhAx27MHpoENcB2ZdSsLTNxmKD+WEPnZigo62Qc8zjGnNxoSE/5Q==",
+ "dependencies": {
+ "dequal": "^2.0.3"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@restart/ui/node_modules/uncontrollable": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz",
+ "integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==",
+ "peerDependencies": {
+ "react": ">=16.14.0"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -3625,6 +3691,14 @@
"url": "https://github.com/sponsors/gregberge"
}
},
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
"node_modules/@testing-library/dom": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz",
@@ -4186,6 +4260,14 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-transition-group": {
+ "version": "4.4.12",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
+ "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
+ "peerDependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@@ -4257,6 +4339,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
},
+ "node_modules/@types/warning": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
+ "integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q=="
+ },
"node_modules/@types/ws": {
"version": "8.5.10",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
@@ -5847,6 +5934,11 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz",
"integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q=="
},
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
+ },
"node_modules/clean-css": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
@@ -6862,6 +6954,15 @@
"utila": "~0.4"
}
},
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
@@ -8975,6 +9076,16 @@
"he": "bin/he"
}
},
+ "node_modules/holder": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/holder/-/holder-0.0.0.tgz",
+ "integrity": "sha512-AQm6tAlYepnCwVFhkORoSyv4eOZBlLEQS+Eb8XkUGVuq2GQXS+prp6Gx9mecaJ3VcRR4RMTmkD2aV2tqr7kRUA=="
+ },
+ "node_modules/holderjs": {
+ "version": "2.9.9",
+ "resolved": "https://registry.npmjs.org/holderjs/-/holderjs-2.9.9.tgz",
+ "integrity": "sha512-ceWPz1MrR3dxOoZXiom+G48+l1VPG3TcjBw9fq5iwCiZAMvYX8Aia13GOxT7DoV/AcSyTH7Vvr11ygjZP9qn4w=="
+ },
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -9364,6 +9475,14 @@
"node": ">= 0.4"
}
},
+ "node_modules/invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
"node_modules/ipaddr.js": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
@@ -14497,6 +14616,23 @@
"react-is": "^16.13.1"
}
},
+ "node_modules/prop-types-extra": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
+ "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
+ "dependencies": {
+ "react-is": "^16.3.2",
+ "warning": "^4.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=0.14.0"
+ }
+ },
+ "node_modules/prop-types-extra/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
"node_modules/prop-types/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -14671,6 +14807,36 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
+ "node_modules/react-bootstrap": {
+ "version": "2.10.9",
+ "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.9.tgz",
+ "integrity": "sha512-TJUCuHcxdgYpOqeWmRApM/Dy0+hVsxNRFvq2aRFQuxhNi/+ivOxC5OdWIeHS3agxvzJ4Ev4nDw2ZdBl9ymd/JQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.24.7",
+ "@restart/hooks": "^0.4.9",
+ "@restart/ui": "^1.9.4",
+ "@types/prop-types": "^15.7.12",
+ "@types/react-transition-group": "^4.4.6",
+ "classnames": "^2.3.2",
+ "dom-helpers": "^5.2.1",
+ "invariant": "^2.2.4",
+ "prop-types": "^15.8.1",
+ "prop-types-extra": "^1.1.0",
+ "react-transition-group": "^4.4.5",
+ "uncontrollable": "^7.2.1",
+ "warning": "^4.0.3"
+ },
+ "peerDependencies": {
+ "@types/react": ">=16.14.8",
+ "react": ">=16.14.0",
+ "react-dom": ">=16.14.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
@@ -14867,6 +15033,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
+ "node_modules/react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
"node_modules/react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@@ -14947,6 +15118,21 @@
}
}
},
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -16804,9 +16990,9 @@
}
},
"node_modules/tslib": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
- "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
},
"node_modules/tsutils": {
"version": "3.21.0",
@@ -16972,6 +17158,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/uncontrollable": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
+ "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.6.3",
+ "@types/react": ">=16.9.11",
+ "invariant": "^2.2.4",
+ "react-lifecycles-compat": "^3.0.4"
+ },
+ "peerDependencies": {
+ "react": ">=15.0.0"
+ }
+ },
"node_modules/underscore": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
@@ -17194,6 +17394,14 @@
"makeerror": "1.0.12"
}
},
+ "node_modules/warning": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
+ "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
"node_modules/watchpack": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz",
diff --git a/app/package.json b/app/package.json
index 5e5e059..e97d047 100644
--- a/app/package.json
+++ b/app/package.json
@@ -11,7 +11,10 @@
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"bootstrap": "^5.3.3",
+ "holder": "^0.0.0",
+ "holderjs": "^2.9.9",
"react": "^18.3.1",
+ "react-bootstrap": "^2.10.9",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
diff --git a/app/public/assets/bg.png b/app/public/assets/bg.png
new file mode 100644
index 0000000..562e977
--- /dev/null
+++ b/app/public/assets/bg.png
Binary files differ
diff --git a/app/public/index.html b/app/public/index.html
index 046038e..d1be181 100644
--- a/app/public/index.html
+++ b/app/public/index.html
@@ -1,21 +1,45 @@
<!DOCTYPE html>
<html lang="en">
- <head>
- <meta charset="utf-8" />
- <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <meta name="theme-color" content="#000000" />
- <meta
- name="description"
- content="Zhongheng Liu's online portfolio and personal homepage."
- />
- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
- <!--
+ <head>
+ <meta charset="utf-8" />
+ <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <meta name="theme-color" content="#000000" />
+ <meta
+ name="description"
+ content="Zhongheng Liu's online portfolio and personal homepage."
+ />
+ <script
+ src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"
+ crossorigin
+ ></script>
+
+ <script
+ src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"
+ crossorigin
+ ></script>
+
+ <script
+ src="https://cdn.jsdelivr.net/npm/react-bootstrap@next/dist/react-bootstrap.min.js"
+ crossorigin
+ ></script>
+ <link
+ rel="stylesheet"
+ href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
+ integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
+ crossorigin="anonymous"
+ />
+
+ <script>
+ var Alert = ReactBootstrap.Alert;
+ </script>
+ <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
+ <!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
- <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
- <!--
+ <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
+ <!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
@@ -24,12 +48,12 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
- <title>Zhongheng Liu - About Me</title>
- </head>
- <body>
- <noscript>You need to enable JavaScript to run this app.</noscript>
- <div id="root"></div>
- <!--
+ <title>Zhongheng Liu - About Me</title>
+ </head>
+ <body>
+ <noscript>You need to enable JavaScript to run this app.</noscript>
+ <div id="root"></div>
+ <!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
@@ -39,5 +63,5 @@
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
- </body>
+ </body>
</html>
diff --git a/app/src/App.css b/app/src/App.css
index 74b5e05..79e413e 100644
--- a/app/src/App.css
+++ b/app/src/App.css
@@ -1,31 +1,29 @@
.App {
text-align: center;
}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
+.wip {
+
+ position:fixed;
+ left:0px;
+ bottom:0px;
+ width:100%;
+ background-image: url('assets/wip.jpg');
+ background-repeat: repeat-x;
+ background-size: 10%;
+ text-align: center;
color: white;
+ align-content: center;
+ opacity: 1;
}
-
-.App-link {
- color: #61dafb;
+.wip-text {
+ font-size: x-large;
+ background-color: rgba(0,0,0, 0.5);
+ width: fit-content;
+ margin-top: 0.2rem;
+ margin-left: auto;
+ margin-right: auto;
+ margin-bottom: 0.2rem;
+ opacity: 1;
}
@keyframes App-logo-spin {
diff --git a/app/src/App.tsx b/app/src/App.tsx
index 7d2f7a7..1cbdbe8 100644
--- a/app/src/App.tsx
+++ b/app/src/App.tsx
@@ -1,54 +1,67 @@
-import './App.css';
+import "./App.css";
+import ContentMain from "./Content";
+
+import HomepageNavbar from "./HomepageNavbar";
function App() {
- return (
- <div className="App">
- <div className="aboutme">
- <h1>Zhongheng Liu</h1>
- <p>-- Web developer and GNU/Linux enthusiast.</p>
- <button onClick={() => { window.location.assign("/assets/resume.pdf"); }}>Learn more</button>
- <button onClick={() => { window.location.assign("https://gitlab.com/stvnliu"); }}>My GitLab</button>
- </div>
- <div className="links">
- <h1>Links</h1>
- <p>I host a variety of online applications on my home server. See below for available sites.</p>
- <h3><a href="https://git.stvnliu.me">Project Repository</a></h3>
- <p>A CGit frontend for the underlying Gitolite infrastructure.</p>
- <h3><a href="https://kellnr.stvnliu.me">Publishing site for my Rust projects</a></h3>
- <p>This is a site hosted with Kellnr, a service to handle uploading and downloading Rust crates from the site's API.</p>
- <h3><a href="https://blog.stvnliu.me">My blog</a></h3>
- <p>My personal blog. Content revolves around software development, mathematics, and the occasional rant.</p>
- </div>
- <div className="projects">
- <h1>My projects</h1>
- <p>These are mostly hobbyist programming projects</p>
- <hr></hr>
- <h3><a href='https://gitlab.com/proteinpedia/proteinpedia-next'>
- proteinpedia-next
- </a>
- </h3>
- <p>A content management platform for displaying and managing informatio
- n of proteins and other chemical</p>
- <hr></hr>
- <h3><a href="/assets/paper.pdf">How can privacy and web inter-connectivity be
- enshrined as core principles in self-hosted online chat applications?
- </a></h3>
- <p>An Edexcel Level 3 Artifact Extended Project Qualification (EPQ) on
- the topic of web chat applications, awarded an A* grade by Edexcel</p>
- <p>You may find the relevant GitLab repositories here:</p>
- <span>
- GitHub repositories for
- <a href="https://github.com/stvnliu/epq-web">web</a> and
- <a href="https://github.com/stvnliu/epq-api">backend API</a>
- </span><br />
- <span>
- GitLab repository for
- <a href="https://gitlab.com/stvnliu/epq-web">web</a> and
- <a href="https://gitlab.com/stvnliu/epq-api">backend API</a>
- </span>
- </div>
- </div>
- );
+ return (
+ <>
+ <HomepageNavbar></HomepageNavbar>
+ <ContentMain />
+ <div className="wip">
+ <p className="wip-text">
+ This website is currently being worked on. Watch out for new content
+ :)
+ </p>
+ </div>
+ </>
+ // <div className="App">
+ // <div className="aboutme">
+ // <h1>Zhongheng Liu</h1>
+ // <p>-- Web developer and GNU/Linux enthusiast.</p>
+ // <button onClick={() => { window.location.assign("/assets/resume.pdf"); }}>Learn more</button>
+ // <button onClick={() => { window.location.assign("https://gitlab.com/stvnliu"); }}>My GitLab</button>
+ // </div>
+ // <div className="links">
+ // <h1>Links</h1>
+ // <p>I host a variety of online applications on my home server. See below for available sites.</p>
+ // <h3><a href="https://git.stvnliu.me">Project Repository</a></h3>
+ // <p>A CGit frontend for the underlying Gitolite infrastructure.</p>
+ // <h3><a href="https://kellnr.stvnliu.me">Publishing site for my Rust projects</a></h3>
+ // <p>This is a site hosted with Kellnr, a service to handle uploading and downloading Rust crates from the site's API.</p>
+ // <h3><a href="https://blog.stvnliu.me">My blog</a></h3>
+ // <p>My personal blog. Content revolves around software development, mathematics, and the occasional rant.</p>
+ // </div>
+ // <div className="projects">
+ // <h1>My projects</h1>
+ // <p>These are mostly hobbyist programming projects</p>
+ // <hr></hr>
+ // <h3><a href='https://gitlab.com/proteinpedia/proteinpedia-next'>
+ // proteinpedia-next
+ // </a>
+ // </h3>
+ // <p>A content management platform for displaying and managing informatio
+ // n of proteins and other chemical</p>
+ // <hr></hr>
+ // <h3><a href="/assets/paper.pdf">How can privacy and web inter-connectivity be
+ // enshrined as core principles in self-hosted online chat applications?
+ // </a></h3>
+ // <p>An Edexcel Level 3 Artifact Extended Project Qualification (EPQ) on
+ // the topic of web chat applications, awarded an A* grade by Edexcel</p>
+ // <p>You may find the relevant GitLab repositories here:</p>
+ // <span>
+ // GitHub repositories for
+ // <a href="https://github.com/stvnliu/epq-web">web</a> and
+ // <a href="https://github.com/stvnliu/epq-api">backend API</a>
+ // </span><br />
+ // <span>
+ // GitLab repository for
+ // <a href="https://gitlab.com/stvnliu/epq-web">web</a> and
+ // <a href="https://gitlab.com/stvnliu/epq-api">backend API</a>
+ // </span>
+ // </div>
+ // </div>
+ );
}
export default App;
diff --git a/app/src/Content.css b/app/src/Content.css
new file mode 100644
index 0000000..50292db
--- /dev/null
+++ b/app/src/Content.css
@@ -0,0 +1,63 @@
+body {
+ height: 100%;
+ background-color: rgb(7, 11, 20);
+}
+.base {
+
+ color: white;
+}
+.first-block {
+ margin: 0;
+ width: 100%;
+ background-image: linear-gradient(to bottom, transparent, rgb(7, 11, 20)), url("assets/bg.png");
+ background-repeat: no-repeat;
+ background-size: 100%;
+ align-content: center;
+}
+.first-block-inner {
+
+ background-color: rgba(58, 75, 94, 0.2);
+ text-align: center;
+ padding: 10%;
+ margin: 2rem;
+}
+.content-block-two-column-left {
+ margin-top: 0;
+ margin-left: 2rem;
+ margin-right: 2rem;
+ display: grid;
+ grid-template-areas:
+ "left right";
+ gap: 1rem;
+ grid-template-columns: 10fr, 1fr;
+}
+.cb-left {
+ margin: 0.5rem;
+ background-color: rgba(58, 75, 94, 0.2);
+ align-content: center;
+}
+.cb-right {
+ margin: 0.5rem;
+ background-color: rgba(58, 75, 94, 0.2);
+ align-content: center;
+}
+.content-block-two-column-left > .cb-left {
+ grid-area: left;
+}
+.content-block-two-column-left > .cb-right {
+ grid-area: right;
+}
+.content-block-two-column-right {
+ margin: 2rem;
+ display: grid;
+ grid-template-areas:
+ "left right";
+ gap: 1rem;
+ grid-template-columns: 1fr, 3fr;
+}
+.content-block-two-column-right > .cb-left {
+ grid-area: left;
+}
+.content-block-two-column-right > .cb-right {
+ grid-area: right;
+} \ No newline at end of file
diff --git a/app/src/Content.tsx b/app/src/Content.tsx
new file mode 100644
index 0000000..1c1252f
--- /dev/null
+++ b/app/src/Content.tsx
@@ -0,0 +1,54 @@
+import { Component } from "react";
+import "./Content.css";
+import { Button, ButtonGroup } from "react-bootstrap";
+
+export interface ContentProps {
+ left: JSX.Element;
+ right: JSX.Element;
+}
+function ContentBlock({ left, right }: ContentProps) {
+ return (
+ <div className="content-block-two-column-left">
+ <div className="cb-left">{left}</div>
+ <div className="cb-right">{right}</div>
+ </div>
+ );
+}
+function ContentMain() {
+ return (
+ <div className="base">
+ <div className="first-block">
+ <div className="first-block-inner">
+ <h1>Steven Liu</h1>
+ <p className="tagline">writing, building, and sharing code.</p>
+ <br />
+ <ButtonGroup>
+ <Button href="https://files.stvnliu.me/cv.pdf">
+ My Resume (CV)
+ </Button>
+ <Button
+ className="bg-body-tertiary"
+ data-bs-theme="dark"
+ href="https://gitlab.com/stvnliu"
+ >
+ My GitLab
+ </Button>
+ <Button
+ className="bg-body-tertiary"
+ data-bs-theme="dark"
+ href="https://blog.stvnliu.me"
+ >
+ Blog
+ </Button>
+ </ButtonGroup>
+ </div>
+ </div>
+
+ {/* <ContentBlock
+ left={<p className="content-block-column-priority">Hello, </p>}
+ right={<p className="content-block-column">World</p>}
+ ></ContentBlock> */}
+ </div>
+ );
+}
+export default ContentMain;
diff --git a/app/src/HomepageNavbar.tsx b/app/src/HomepageNavbar.tsx
new file mode 100644
index 0000000..9649aef
--- /dev/null
+++ b/app/src/HomepageNavbar.tsx
@@ -0,0 +1,39 @@
+import { Container, Image, Nav, Navbar, NavDropdown } from "react-bootstrap";
+import ContentBlock from "./Content";
+function HomepageNavbar() {
+ return (
+ <Navbar expand="lg" className="bg-body-tertiary" data-bs-theme="dark">
+ <Container>
+ <Navbar.Brand href="#home">My Homepage</Navbar.Brand>
+ <Navbar.Toggle aria-controls="basic-navbar-nav" />
+ <Navbar.Collapse id="basic-navbar-nav">
+ <Nav className="me-auto">
+ <Nav.Link href="#home">Home</Nav.Link>
+ <NavDropdown title="Links" id="basic-nav-dropdown1">
+ <NavDropdown.Item href="https://gitlab.com/stvnliu">
+ GitLab
+ </NavDropdown.Item>
+ <NavDropdown.Item href="https://www.linkedin.com/in/zhongheng-liu/">
+ LinkedIn
+ </NavDropdown.Item>
+ </NavDropdown>
+ <NavDropdown title="Projects" id="basic-nav-dropdown2">
+ <NavDropdown.Item href="https://files.stvnliu.me/extended_project/EPQ-Explanation-20240424-FINAL.pdf">
+ Extended Project
+ </NavDropdown.Item>
+ <NavDropdown.Item href="#action/3.2">
+ Another action
+ </NavDropdown.Item>
+ <NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
+ <NavDropdown.Divider />
+ <NavDropdown.Item href="#action/3.4">
+ Separated link
+ </NavDropdown.Item>
+ </NavDropdown>
+ </Nav>
+ </Navbar.Collapse>
+ </Container>
+ </Navbar>
+ );
+}
+export default HomepageNavbar;
diff --git a/app/src/assets/bg.png b/app/src/assets/bg.png
new file mode 100644
index 0000000..562e977
--- /dev/null
+++ b/app/src/assets/bg.png
Binary files differ
diff --git a/app/src/assets/wip.jpg b/app/src/assets/wip.jpg
new file mode 100644
index 0000000..f2def1b
--- /dev/null
+++ b/app/src/assets/wip.jpg
Binary files differ
diff --git a/public/index.html b/public/index.html
index 3a92f33..d593d0f 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1 +1,46 @@
-<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.43634271.js"></script><link href="/static/css/main.f855e6bc.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html> \ No newline at end of file
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8" />
+ <script
+ src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"
+ crossorigin
+ ></script>
+
+ <script
+ src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"
+ crossorigin
+ ></script>
+
+ <script
+ src="https://cdn.jsdelivr.net/npm/react-bootstrap@next/dist/react-bootstrap.min.js"
+ crossorigin
+ ></script>
+ <link
+ rel="stylesheet"
+ href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
+ integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
+ crossorigin="anonymous"
+ />
+
+ <script>
+ var Alert = ReactBootstrap.Alert;
+ </script>
+ <link rel="icon" href="/favicon.ico" />
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
+ <meta name="theme-color" content="#000000" />
+ <meta
+ name="description"
+ content="Web site created using create-react-app"
+ />
+ <link rel="apple-touch-icon" href="/logo192.png" />
+ <link rel="manifest" href="/manifest.json" />
+ <title>React App</title>
+ <script defer="defer" src="/static/js/main.43634271.js"></script>
+ <link href="/static/css/main.f855e6bc.css" rel="stylesheet" />
+ </head>
+ <body>
+ <noscript>You need to enable JavaScript to run this app.</noscript>
+ <div id="root"></div>
+ </body>
+</html>