~repos /website
git clone https://pyrossh.dev/repos/website.git
木 Personal website of pyrossh. Built with astrojs, shiki, vite.
97db5184
—
pyrossh 1 year ago
improve
- .gitignore +1 -1
- LemonDrop.tsx +0 -74
- README.md +0 -38
- jsconfig.json +0 -4
- package-lock.json +61 -15
- package.json +11 -6
- routes/_404.tsx +0 -30
- routes/_app.tsx +0 -28
- routes/cv.tsx +0 -235
- routes/index.tsx +0 -252
- routes/posts.tsx +0 -96
- routes/stats.tsx +0 -42
- scripts/makePdf.ts +0 -19
- src/app.html +5 -8
- src/error.html +0 -19
- src/lib/components/Footer.svelte +3 -3
- src/lib/components/Slide.svelte +1 -1
- src/lib/index.js +0 -3
- src/routes/+error.svelte +29 -0
- src/routes/+layout.svelte +7 -2
- src/routes/+page.svelte +60 -33
- src/routes/cv/+page.svelte +196 -0
- src/routes/posts/+page.svelte +198 -0
- static/favicon.png +0 -0
- {design → static}/logo.curve +0 -0
- static/logo.svg +0 -6
- static/styles.css +0 -438
- svelte.config.js +9 -6
- tailwind.config.ts +0 -28
- uno.config.ts +17 -14
.gitignore
CHANGED
|
@@ -7,4 +7,4 @@ node_modules
|
|
|
7
7
|
.env.*
|
|
8
8
|
!.env.example
|
|
9
9
|
vite.config.js.timestamp-*
|
|
10
|
-
vite.config.ts.timestamp-*
|
|
10
|
+
vite.config.ts.timestamp-*
|
LemonDrop.tsx
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef } from "preact/hooks";
|
|
2
|
-
import { useSignal } from "@preact/signals";
|
|
3
|
-
|
|
4
|
-
function easeInCirc(x: number) {
|
|
5
|
-
return 1 - Math.sqrt(1 - Math.pow(x, 2));
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function LemonDrop() {
|
|
9
|
-
const counter = useSignal(0);
|
|
10
|
-
const dropy = useSignal(60);
|
|
11
|
-
const requestIdRef = useRef<number>();
|
|
12
|
-
const juice = `M18 ${63 + counter.value} C15 ${63 + counter.value} 16 ${
|
|
13
|
-
63 + counter.value
|
|
14
|
-
} 12 61L9 56C2 33 62 -3 80 12C103 27 44 56 29 58C27 58 25 59 24 61C20 ${
|
|
15
|
-
63 + counter.value
|
|
16
|
-
} 21 ${63 + counter.value} 18 ${63 + counter.value}Z`;
|
|
17
|
-
|
|
18
|
-
function updateJuice(timestamp: number) {
|
|
19
|
-
const amp = 40;
|
|
20
|
-
const x = timestamp / 2000;
|
|
21
|
-
const saw = x - Math.floor(x);
|
|
22
|
-
if (saw < 0.6) {
|
|
23
|
-
counter.value = easeInCirc(saw) * amp;
|
|
24
|
-
dropy.value = -100;
|
|
25
|
-
} else {
|
|
26
|
-
counter.value = easeInCirc(1 - saw) * amp * 0.1;
|
|
27
|
-
dropy.value = 70 + Math.pow(saw - 0.6, 2) * 10000;
|
|
28
|
-
}
|
|
29
|
-
requestIdRef.current = globalThis.requestAnimationFrame(updateJuice);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
requestIdRef.current = requestAnimationFrame(updateJuice);
|
|
34
|
-
|
|
35
|
-
return () => {
|
|
36
|
-
if (requestIdRef.current !== undefined) {
|
|
37
|
-
cancelAnimationFrame(requestIdRef.current);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
}, []);
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<svg
|
|
44
|
-
width="32"
|
|
45
|
-
height="48"
|
|
46
|
-
viewBox="0 0 100 120"
|
|
47
|
-
fill="none"
|
|
48
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
49
|
-
role="img"
|
|
50
|
-
aria-label="Fresh logo"
|
|
51
|
-
>
|
|
52
|
-
<circle cx="18" cy={dropy.value} r="4" fill="white"></circle>
|
|
53
|
-
<path
|
|
54
|
-
d="M11.9 96.3v24H7v-24h4.9Zm7.5 10.2v4h-8.8v-4h8.8Zm1-10.2v4h-9.8v-4h9.8ZM23.2 96.3H31c1.6 0 3 .3 4.1.9 1.1.5 2 1.3 2.6 2.4a8 8 0 0 1 1 4c0 1.3-.2 2.4-.6 3.3-.3 1-.8 1.7-1.5 2.3-.7.6-1.4 1-2.3 1.5l-1.5.8h-6.3v-4h4.3a3 3 0 0 0 1.7-.4c.4-.3.7-.7 1-1.2a5 5 0 0 0 .3-2c0-.7-.1-1.3-.3-1.9-.2-.5-.5-1-1-1.2-.3-.3-.9-.5-1.5-.5h-3v20h-4.8v-24Zm11 24-4.4-10.7h5l4.6 10.5v.2h-5.2ZM55.9 116.3v4H45.4v-4h10.5Zm-9-20v24H42v-24H47Zm7.6 9.8v3.8h-9.1v-3.8h9Zm1.4-9.8v4H45.4v-4h10.5ZM69 114c0-.4 0-.8-.2-1.1 0-.4-.2-.7-.5-1l-1-1-1.9-.8-2.6-1.2-2.2-1.5a6.5 6.5 0 0 1-1.7-2 6 6 0 0 1-.5-2.7c0-1 .1-2 .5-2.7a6 6 0 0 1 1.6-2.2c.7-.5 1.5-1 2.4-1.3a9.5 9.5 0 0 1 7.1.5c1.2.6 2 1.5 2.7 2.6.6 1 1 2.4 1 3.8h-5a5 5 0 0 0-.2-1.8c-.2-.5-.5-1-1-1.2-.4-.3-1-.5-1.6-.5-.6 0-1.1.2-1.5.4-.4.2-.7.6-1 1l-.2 1.4c0 .4.1.8.3 1.1l.8.8a21.3 21.3 0 0 0 2.8 1.4l2.9 1.4a9 9 0 0 1 2 1.8c.7.6 1 1.3 1.4 2a7.9 7.9 0 0 1-.1 5.5c-.4.8-.9 1.5-1.5 2.1a7 7 0 0 1-2.5 1.4c-2 .5-1 1.8-3 1.8s-1.3-1.5-3.2-1.8c-1-.3-2-.8-2.7-1.4a6.7 6.7 0 0 1-1.8-2.5c-.4-1-.6-2.2-.6-3.5h4.9c0 .7 0 1.3.2 1.8.1.5.3 1 .6 1.3.3.2.7.5 1.1.6.5.2 1 .2 1.5.2.7 0 1.2 0 1.6-.3.4-.3.6-.6.8-1 .2-.4.3-.9.3-1.4ZM90.5 106v4h-10v-4h10Zm-8.6-9.7v24h-4.8v-24h4.8Zm12.1 0v24h-4.8v-24H94Z"
|
|
55
|
-
fill="#FFFFFF"
|
|
56
|
-
/>
|
|
57
|
-
<path
|
|
58
|
-
d="M84 16c13 27 1 52-7 59 0 4-9 9-12 7-12 5-38-2-53-21-6-7 1-21 21-36 13-10 33-17 51-9Z"
|
|
59
|
-
fill="#FFD80B"
|
|
60
|
-
/>
|
|
61
|
-
<path d={juice} fill="white" />
|
|
62
|
-
<path
|
|
63
|
-
d="M69 15c15-1 9 10-6 19L44 44c-2 1-4-2-6 0l-3 6c-3 1-13 3-16 2-5-2-5-9 5-18l7-4c-1-2-1-2 2-5 3-2 19-10 29-11l1 2 6-1Z"
|
|
64
|
-
fill="#FFED4E"
|
|
65
|
-
/>
|
|
66
|
-
<path
|
|
67
|
-
d="M38 35c1-1 3-2 3-4l8-3c0 1-1 3 1 4-2 1-7 1-8 5-1-2-1-2-4-2Z"
|
|
68
|
-
fill="#fff"
|
|
69
|
-
/>
|
|
70
|
-
</svg>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export default LemonDrop;
|
README.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# create-svelte
|
|
2
|
-
|
|
3
|
-
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
|
|
4
|
-
|
|
5
|
-
## Creating a project
|
|
6
|
-
|
|
7
|
-
If you're seeing this, you've probably already done this step. Congrats!
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# create a new project in the current directory
|
|
11
|
-
npm create svelte@latest
|
|
12
|
-
|
|
13
|
-
# create a new project in my-app
|
|
14
|
-
npm create svelte@latest my-app
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Developing
|
|
18
|
-
|
|
19
|
-
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
npm run dev
|
|
23
|
-
|
|
24
|
-
# or start the server and open the app in a new browser tab
|
|
25
|
-
npm run dev -- --open
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Building
|
|
29
|
-
|
|
30
|
-
To create a production version of your app:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm run build
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
You can preview the production build with `npm run preview`.
|
|
37
|
-
|
|
38
|
-
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
jsconfig.json
CHANGED
|
@@ -11,8 +11,4 @@
|
|
|
11
11
|
"strict": true,
|
|
12
12
|
"moduleResolution": "bundler"
|
|
13
13
|
}
|
|
14
|
-
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias and https://kit.svelte.dev/docs/configuration#files
|
|
15
|
-
//
|
|
16
|
-
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
|
17
|
-
// from the referenced tsconfig.json - TypeScript does not merge them in
|
|
18
14
|
}
|
package-lock.json
CHANGED
|
@@ -11,10 +11,15 @@
|
|
|
11
11
|
"@unocss/reset": "^0.58.5"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
|
+
"@iconify-json/clarity": "^1.1.12",
|
|
15
|
+
"@iconify-json/eos-icons": "^1.1.10",
|
|
16
|
+
"@iconify-json/ic": "^1.1.17",
|
|
17
|
+
"@iconify-json/icon-park": "^1.1.13",
|
|
18
|
+
"@iconify-json/logos": "^1.1.42",
|
|
14
19
|
"@iconify-json/mdi": "^1.1.64",
|
|
15
|
-
"@iconify
|
|
20
|
+
"@iconify-json/typcn": "^1.1.9",
|
|
16
21
|
"@playwright/test": "^1.28.1",
|
|
17
|
-
"@sveltejs/adapter-
|
|
22
|
+
"@sveltejs/adapter-static": "^3.0.1",
|
|
18
23
|
"@sveltejs/kit": "^2.0.0",
|
|
19
24
|
"@types/eslint": "8.56.0",
|
|
20
25
|
"@unocss/svelte-scoped": "^0.58.5",
|
|
@@ -1164,6 +1169,51 @@
|
|
|
1164
1169
|
"integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
|
|
1165
1170
|
"dev": true
|
|
1166
1171
|
},
|
|
1172
|
+
"node_modules/@iconify-json/clarity": {
|
|
1173
|
+
"version": "1.1.12",
|
|
1174
|
+
"resolved": "https://registry.npmjs.org/@iconify-json/clarity/-/clarity-1.1.12.tgz",
|
|
1175
|
+
"integrity": "sha512-Qho+7l2znCxMlmNfNRk3LFsXJZX1d8H8v9q+UIkzuiHuS4YI3tl5SpYrPQ4HdhGnzAJbOXhGBb1JPL+mgqc0Ow==",
|
|
1176
|
+
"dev": true,
|
|
1177
|
+
"dependencies": {
|
|
1178
|
+
"@iconify/types": "*"
|
|
1179
|
+
}
|
|
1180
|
+
},
|
|
1181
|
+
"node_modules/@iconify-json/eos-icons": {
|
|
1182
|
+
"version": "1.1.10",
|
|
1183
|
+
"resolved": "https://registry.npmjs.org/@iconify-json/eos-icons/-/eos-icons-1.1.10.tgz",
|
|
1184
|
+
"integrity": "sha512-sLkaMSrzHgATDFpVYs3/ymeNxR8CtkZCh1Ds9fYxjfhNmXArofbWhHwANqM4Sw9XNbMJq/Z5yxJ5BPTYqjhRcA==",
|
|
1185
|
+
"dev": true,
|
|
1186
|
+
"dependencies": {
|
|
1187
|
+
"@iconify/types": "*"
|
|
1188
|
+
}
|
|
1189
|
+
},
|
|
1190
|
+
"node_modules/@iconify-json/ic": {
|
|
1191
|
+
"version": "1.1.17",
|
|
1192
|
+
"resolved": "https://registry.npmjs.org/@iconify-json/ic/-/ic-1.1.17.tgz",
|
|
1193
|
+
"integrity": "sha512-EvAjZzVESmN36zlyefylePUNaU2BQ3eRKVZ6KQSQ2bG01ppoZaiFZRri74VTyvp5Mlv2yn68ux1fgCoT+etGmA==",
|
|
1194
|
+
"dev": true,
|
|
1195
|
+
"dependencies": {
|
|
1196
|
+
"@iconify/types": "*"
|
|
1197
|
+
}
|
|
1198
|
+
},
|
|
1199
|
+
"node_modules/@iconify-json/icon-park": {
|
|
1200
|
+
"version": "1.1.13",
|
|
1201
|
+
"resolved": "https://registry.npmjs.org/@iconify-json/icon-park/-/icon-park-1.1.13.tgz",
|
|
1202
|
+
"integrity": "sha512-7AoB802JUeMwaJBRz1a+3PGfifxDiMiE+mVgbDPZLHgLaLq7WXslQCV0aDs8kQHF0SGIBUp7f8kKTHGUktuFtw==",
|
|
1203
|
+
"dev": true,
|
|
1204
|
+
"dependencies": {
|
|
1205
|
+
"@iconify/types": "*"
|
|
1206
|
+
}
|
|
1207
|
+
},
|
|
1208
|
+
"node_modules/@iconify-json/logos": {
|
|
1209
|
+
"version": "1.1.42",
|
|
1210
|
+
"resolved": "https://registry.npmjs.org/@iconify-json/logos/-/logos-1.1.42.tgz",
|
|
1211
|
+
"integrity": "sha512-/f+frtPm3m3Z30oy8Pk+QqRDkbmAiIaWGPl5CmsCXm15MVfvw9a/V/gD7WzdyuSGAZcFuQaqbHXj92y/n+2ifg==",
|
|
1212
|
+
"dev": true,
|
|
1213
|
+
"dependencies": {
|
|
1214
|
+
"@iconify/types": "*"
|
|
1215
|
+
}
|
|
1216
|
+
},
|
|
1167
1217
|
"node_modules/@iconify-json/mdi": {
|
|
1168
1218
|
"version": "1.1.64",
|
|
1169
1219
|
"resolved": "https://registry.npmjs.org/@iconify-json/mdi/-/mdi-1.1.64.tgz",
|
|
@@ -1173,14 +1223,13 @@
|
|
|
1173
1223
|
"@iconify/types": "*"
|
|
1174
1224
|
}
|
|
1175
1225
|
},
|
|
1176
|
-
"node_modules/@iconify
|
|
1226
|
+
"node_modules/@iconify-json/typcn": {
|
|
1177
|
-
"version": "
|
|
1227
|
+
"version": "1.1.9",
|
|
1178
|
-
"resolved": "https://registry.npmjs.org/@iconify
|
|
1228
|
+
"resolved": "https://registry.npmjs.org/@iconify-json/typcn/-/typcn-1.1.9.tgz",
|
|
1179
|
-
"integrity": "sha512-
|
|
1229
|
+
"integrity": "sha512-irILpgqFdk6IWd7HHzwWe1oGEe4nKe850mG3Iu2g6zKPKzGqcY8CD+U+yBSk5wBa8JsVQ823Weez8N8zAKkTyQ==",
|
|
1180
1230
|
"dev": true,
|
|
1181
1231
|
"dependencies": {
|
|
1182
|
-
"@iconify/types": "*"
|
|
1232
|
+
"@iconify/types": "*"
|
|
1183
|
-
"pathe": "^1.1.2"
|
|
1184
1233
|
}
|
|
1185
1234
|
},
|
|
1186
1235
|
"node_modules/@iconify/types": {
|
|
@@ -1643,14 +1692,11 @@
|
|
|
1643
1692
|
"integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
|
|
1644
1693
|
"dev": true
|
|
1645
1694
|
},
|
|
1646
|
-
"node_modules/@sveltejs/adapter-
|
|
1695
|
+
"node_modules/@sveltejs/adapter-static": {
|
|
1647
|
-
"version": "3.
|
|
1696
|
+
"version": "3.0.1",
|
|
1648
|
-
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-
|
|
1697
|
+
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.1.tgz",
|
|
1649
|
-
"integrity": "sha512-
|
|
1698
|
+
"integrity": "sha512-6lMvf7xYEJ+oGeR5L8DFJJrowkefTK6ZgA4JiMqoClMkKq0s6yvsd3FZfCFvX1fQ0tpCD7fkuRVHsnUVgsHyNg==",
|
|
1650
1699
|
"dev": true,
|
|
1651
|
-
"dependencies": {
|
|
1652
|
-
"import-meta-resolve": "^4.0.0"
|
|
1653
|
-
},
|
|
1654
1700
|
"peerDependencies": {
|
|
1655
1701
|
"@sveltejs/kit": "^2.0.0"
|
|
1656
1702
|
}
|
package.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"name": "website",
|
|
3
3
|
"version": "0.0.1",
|
|
4
4
|
"private": true,
|
|
5
|
+
"type": "module",
|
|
5
6
|
"scripts": {
|
|
6
7
|
"dev": "vite dev",
|
|
7
8
|
"build": "vite build",
|
|
@@ -14,11 +15,19 @@
|
|
|
14
15
|
"test:integration": "playwright test",
|
|
15
16
|
"test:unit": "vitest"
|
|
16
17
|
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@unocss/reset": "^0.58.5"
|
|
20
|
+
},
|
|
17
21
|
"devDependencies": {
|
|
22
|
+
"@iconify-json/clarity": "^1.1.12",
|
|
23
|
+
"@iconify-json/eos-icons": "^1.1.10",
|
|
24
|
+
"@iconify-json/ic": "^1.1.17",
|
|
25
|
+
"@iconify-json/icon-park": "^1.1.13",
|
|
26
|
+
"@iconify-json/logos": "^1.1.42",
|
|
18
27
|
"@iconify-json/mdi": "^1.1.64",
|
|
19
|
-
"@iconify
|
|
28
|
+
"@iconify-json/typcn": "^1.1.9",
|
|
20
29
|
"@playwright/test": "^1.28.1",
|
|
21
|
-
"@sveltejs/adapter-
|
|
30
|
+
"@sveltejs/adapter-static": "^3.0.1",
|
|
22
31
|
"@sveltejs/kit": "^2.0.0",
|
|
23
32
|
"@types/eslint": "8.56.0",
|
|
24
33
|
"@unocss/svelte-scoped": "^0.58.5",
|
|
@@ -35,9 +44,5 @@
|
|
|
35
44
|
"unocss": "^0.58.5",
|
|
36
45
|
"vite": "^5.0.3",
|
|
37
46
|
"vitest": "^1.2.0"
|
|
38
|
-
},
|
|
39
|
-
"type": "module",
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"@unocss/reset": "^0.58.5"
|
|
42
47
|
}
|
|
43
48
|
}
|
routes/_404.tsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Head } from "$fresh/runtime.ts";
|
|
2
|
-
import { PageProps } from "$fresh/server.ts";
|
|
3
|
-
|
|
4
|
-
export default function Error404({ url }: PageProps) {
|
|
5
|
-
return (
|
|
6
|
-
<>
|
|
7
|
-
<Head>
|
|
8
|
-
<title slot="head">pyros.sh | Page Not Found</title>
|
|
9
|
-
<meta name="description" content="Page Not Found" />
|
|
10
|
-
</Head>
|
|
11
|
-
<div class="px-4 py-8 mx-auto">
|
|
12
|
-
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
|
|
13
|
-
<img
|
|
14
|
-
class="my-6"
|
|
15
|
-
src="/logo.svg"
|
|
16
|
-
width="128"
|
|
17
|
-
height="128"
|
|
18
|
-
alt="the Fresh logo: a sliced lemon dripping with juice"
|
|
19
|
-
/>
|
|
20
|
-
<h1 class="text-4xl font-bold">404 - Page not found</h1>
|
|
21
|
-
<p class="my-4">The page you were looking for doesn't exist.</p>
|
|
22
|
-
<pre>Path: {url.pathname}</pre>
|
|
23
|
-
<a href="/" class="underline mt-4">
|
|
24
|
-
Go back home
|
|
25
|
-
</a>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
</>
|
|
29
|
-
);
|
|
30
|
-
}
|
routes/_app.tsx
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { PageProps } from "$fresh/server.ts";
|
|
2
|
-
import { asset } from "$fresh/runtime.ts";
|
|
3
|
-
import Footer from "../src/components_old/Footer.tsx";
|
|
4
|
-
import Header from "../src/components_old/Header.tsx";
|
|
5
|
-
|
|
6
|
-
export default function App({ Component, url }: PageProps) {
|
|
7
|
-
const isStatsPage = url.pathname.includes("/stats");
|
|
8
|
-
const bodyStyle = isStatsPage ? { background: "#F8F5ED" } : {};
|
|
9
|
-
return (
|
|
10
|
-
<html lang="en" class="h-full w-full">
|
|
11
|
-
<head>
|
|
12
|
-
<link rel="canonical" href={url.toString()} />
|
|
13
|
-
<meta property="og:url" content={url.toString()} />
|
|
14
|
-
</head>
|
|
15
|
-
<body class="leading-8 flex flex-1 flex-col font-normal text-lg sm:leading-7 m-0">
|
|
16
|
-
<Header />
|
|
17
|
-
<main class="w-full h-full block bg-white" style={bodyStyle}>
|
|
18
|
-
<div class="flex w-full flex-1 flex-row justify-center">
|
|
19
|
-
<div class="flex w-full flex-1 flex-row items-center max-w-5xl mt-4 mb-20 p-4">
|
|
20
|
-
<Component />
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
</main>
|
|
24
|
-
<Footer />
|
|
25
|
-
</body>
|
|
26
|
-
</html>
|
|
27
|
-
);
|
|
28
|
-
}
|
routes/cv.tsx
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { asset, Head } from "$fresh/runtime.ts";
|
|
2
|
-
|
|
3
|
-
export default function CV() {
|
|
4
|
-
return (
|
|
5
|
-
<div class="mx-auto">
|
|
6
|
-
<Head>
|
|
7
|
-
<title>pyros.sh | CV</title>
|
|
8
|
-
<meta name="description" content="Peter John's CV" />
|
|
9
|
-
</Head>
|
|
10
|
-
<div class="cv-page">
|
|
11
|
-
<section>
|
|
12
|
-
<h3>Equal Experts</h3>
|
|
13
|
-
<h4>Software Developer, Oct 2018 - present</h4>
|
|
14
|
-
<h5>
|
|
15
|
-
Making Software. Better. Equal Experts is a network of talented,
|
|
16
|
-
experienced software consultants, specialising in agile delivery.
|
|
17
|
-
</h5>
|
|
18
|
-
<div>
|
|
19
|
-
These are the client projects I worked on,
|
|
20
|
-
<ul>
|
|
21
|
-
<li>
|
|
22
|
-
<b>John Lewis</b>
|
|
23
|
-
<ul>
|
|
24
|
-
<li>
|
|
25
|
-
Built a social quiz game to improve engagement across the
|
|
26
|
-
website
|
|
27
|
-
</li>
|
|
28
|
-
<li>
|
|
29
|
-
Implemented new functionality in customer self serve
|
|
30
|
-
functions like returns, cancellations, tracking.
|
|
31
|
-
</li>
|
|
32
|
-
<li>
|
|
33
|
-
Refactored the old self serve reactjs app to use nextjs and
|
|
34
|
-
removed a large redux dependency thereby simplifying the
|
|
35
|
-
codebase.
|
|
36
|
-
</li>
|
|
37
|
-
<li>
|
|
38
|
-
Ran many experiments in the customer services and order
|
|
39
|
-
pages to improve our metrics and reduce contacts.
|
|
40
|
-
</li>
|
|
41
|
-
<li>
|
|
42
|
-
Built the new Product Description Page (PDP) for Simple
|
|
43
|
-
Carpets using a micro frontend architecture.
|
|
44
|
-
</li>
|
|
45
|
-
</ul>
|
|
46
|
-
</li>
|
|
47
|
-
<li>
|
|
48
|
-
<b>iOWNA</b>
|
|
49
|
-
<ul>
|
|
50
|
-
<li>
|
|
51
|
-
Built a content editor for curators to create content on our
|
|
52
|
-
platform
|
|
53
|
-
</li>
|
|
54
|
-
<li>
|
|
55
|
-
Built the iOWNA crossplatform app in react-native that works
|
|
56
|
-
in android, ios, and web using one codebase.
|
|
57
|
-
</li>
|
|
58
|
-
<li>
|
|
59
|
-
Implemented admin specific functionalities in the web app
|
|
60
|
-
</li>
|
|
61
|
-
<li>
|
|
62
|
-
Implemented an in-app OTA update method using expo and
|
|
63
|
-
semantic versionin
|
|
64
|
-
</li>
|
|
65
|
-
<li>Built the iOWNA marketing website</li>
|
|
66
|
-
<li>
|
|
67
|
-
Built the Health Questionnaire clinician/patient feedback
|
|
68
|
-
form feature with push notifications
|
|
69
|
-
</li>
|
|
70
|
-
</ul>
|
|
71
|
-
</li>
|
|
72
|
-
<li>
|
|
73
|
-
<b>Zeta</b>
|
|
74
|
-
<ul>
|
|
75
|
-
<li>
|
|
76
|
-
Added multiple download formats (pdf,html,xlsx) for reports
|
|
77
|
-
in the Reporting Center
|
|
78
|
-
</li>
|
|
79
|
-
<li>
|
|
80
|
-
Created a Groovy Script to automate creating ACL in sandbox
|
|
81
|
-
authorization framework
|
|
82
|
-
</li>
|
|
83
|
-
<li>
|
|
84
|
-
Integrated Camunda Workflow Engine into Zeta services in
|
|
85
|
-
Operations Center
|
|
86
|
-
</li>
|
|
87
|
-
<li>
|
|
88
|
-
Built a few workflows on Camunda and integrated it with some
|
|
89
|
-
internal services
|
|
90
|
-
</li>
|
|
91
|
-
<li>
|
|
92
|
-
Built a custom k8s CRD using the operator framework to
|
|
93
|
-
automate creating ACL in sandbox using custom resources
|
|
94
|
-
</li>
|
|
95
|
-
</ul>
|
|
96
|
-
</li>
|
|
97
|
-
<li>
|
|
98
|
-
<b>Lifebox</b>
|
|
99
|
-
<ul>
|
|
100
|
-
<li>
|
|
101
|
-
Added search functionality to the hospital procedure codes
|
|
102
|
-
</li>
|
|
103
|
-
<li>
|
|
104
|
-
Converted the Health Questionnaire from json to native go
|
|
105
|
-
code making it easier to make changes to it
|
|
106
|
-
</li>
|
|
107
|
-
<li>
|
|
108
|
-
Integrated with SAP using HL7 message format to create
|
|
109
|
-
patients, episodes, schedule/cancel procedures
|
|
110
|
-
</li>
|
|
111
|
-
<li>
|
|
112
|
-
Built the Patient Document repository for uploading,
|
|
113
|
-
downloading patient files
|
|
114
|
-
</li>
|
|
115
|
-
<li>
|
|
116
|
-
Built the patients online reports view using the data from
|
|
117
|
-
SAP
|
|
118
|
-
</li>
|
|
119
|
-
</ul>
|
|
120
|
-
</li>
|
|
121
|
-
</ul>
|
|
122
|
-
</div>
|
|
123
|
-
</section>
|
|
124
|
-
<section>
|
|
125
|
-
<h3>Numberz</h3>
|
|
126
|
-
<h4>Full Stack Developer, Sept 2016 - Oct 2018</h4>
|
|
127
|
-
<h5>
|
|
128
|
-
Numberz integrates banking with your day-2-day business work-flows
|
|
129
|
-
freeing up a lot of effort, time and heart-burn, to help your
|
|
130
|
-
business grow.
|
|
131
|
-
</h5>
|
|
132
|
-
<ul>
|
|
133
|
-
<li>
|
|
134
|
-
Implemented new features and fixed bugs on the numberz android app
|
|
135
|
-
</li>
|
|
136
|
-
<li>Integrated numberz with Tally ERP</li>
|
|
137
|
-
<li>
|
|
138
|
-
Implemented CI and Devops within out system to ease our deployment
|
|
139
|
-
process using docker and docker-compose
|
|
140
|
-
</li>
|
|
141
|
-
<li>
|
|
142
|
-
Created a slack bot called deploybot which was used to deploy our
|
|
143
|
-
microservices to our servers
|
|
144
|
-
</li>
|
|
145
|
-
<li>
|
|
146
|
-
Started tech talks on Thursdays to discuss cutting edge
|
|
147
|
-
technologies
|
|
148
|
-
</li>
|
|
149
|
-
<li>
|
|
150
|
-
Architected and built the Notification Service using rabbitmq and
|
|
151
|
-
nodejs
|
|
152
|
-
</li>
|
|
153
|
-
<li>Built the Multi-User and Multi-Company Features</li>
|
|
154
|
-
<li>
|
|
155
|
-
Implemented and lead a team on integration with the GSTN System so
|
|
156
|
-
that customers could file their GST Taxes within our product
|
|
157
|
-
</li>
|
|
158
|
-
<li>
|
|
159
|
-
Architected and built the numberz Identity Management Service(IMS)
|
|
160
|
-
</li>
|
|
161
|
-
<li>
|
|
162
|
-
Architected our new product called the Numberz Accounts Receivable
|
|
163
|
-
(AR)
|
|
164
|
-
</li>
|
|
165
|
-
<li>Laid down the architecture for the frontend and backend</li>
|
|
166
|
-
<li>
|
|
167
|
-
Built these core features for our new AR Product - Auto Reminders,
|
|
168
|
-
Manual Reminders, User Management, Cash Discounting, CFO Dashboard
|
|
169
|
-
Metrics
|
|
170
|
-
</li>
|
|
171
|
-
</ul>
|
|
172
|
-
</section>
|
|
173
|
-
<section>
|
|
174
|
-
<h3>Playlyfe</h3>
|
|
175
|
-
<h4>Full Stack Developer, Apr 2014 - Sept 2016</h4>
|
|
176
|
-
<h5>
|
|
177
|
-
Playlyfe is an online Gamification Platform which empowers anyone to
|
|
178
|
-
design and implement a gamified system.
|
|
179
|
-
</h5>
|
|
180
|
-
<ul>
|
|
181
|
-
<li>
|
|
182
|
-
Built the Playlyfe Hybrid Mobile app using Phonegap for Android
|
|
183
|
-
and iOS
|
|
184
|
-
</li>
|
|
185
|
-
<li>
|
|
186
|
-
Built the leaderboard system using Mongodb, Redis and Couchbase as
|
|
187
|
-
the datastore
|
|
188
|
-
</li>
|
|
189
|
-
<li>Migration of data from v1 to v2 of the API</li>
|
|
190
|
-
<li>
|
|
191
|
-
Built SDKs for the Playlyfe v2 API in C#, Java, Python, Ruby, PHP,
|
|
192
|
-
Nodejs, Gos
|
|
193
|
-
</li>
|
|
194
|
-
<li>
|
|
195
|
-
Maintained the job server and wrote most of the background jobs
|
|
196
|
-
</li>
|
|
197
|
-
<li>
|
|
198
|
-
Added documentation to most of the REST API and created the
|
|
199
|
-
Developer Console which was Like Swagger UI
|
|
200
|
-
</li>
|
|
201
|
-
<li>Integrated our REST API in Leanosphere's LMS</li>
|
|
202
|
-
<li>
|
|
203
|
-
Integrated the REST API in Knolskape's product Aktivlearn LMS
|
|
204
|
-
</li>
|
|
205
|
-
<li>Integrated the REST API in Linkstreet's LMS</li>
|
|
206
|
-
<li>
|
|
207
|
-
Integrated the REST API in Moodle LMS by creating an admin plugin
|
|
208
|
-
to add Gamification features
|
|
209
|
-
</li>
|
|
210
|
-
<li>
|
|
211
|
-
Rebuilt the core platform in golang for performance and
|
|
212
|
-
developement speed
|
|
213
|
-
</li>
|
|
214
|
-
<li>Built the GraphQL API for our cutting edge product Catalyst</li>
|
|
215
|
-
<li>
|
|
216
|
-
Convinced the boss to create our own scripting language plscript
|
|
217
|
-
for our rule engine.
|
|
218
|
-
</li>
|
|
219
|
-
<li>
|
|
220
|
-
Build a REST API for our product catalyst for a POC with Vodafone
|
|
221
|
-
</li>
|
|
222
|
-
<li>
|
|
223
|
-
Built the Quiz, Review, Match, Tournament features in Catalyst for
|
|
224
|
-
a major project with HP
|
|
225
|
-
</li>
|
|
226
|
-
<li>
|
|
227
|
-
Added gamification features to Saudi Matches a popular game
|
|
228
|
-
tracking app
|
|
229
|
-
</li>
|
|
230
|
-
</ul>
|
|
231
|
-
</section>
|
|
232
|
-
</div>
|
|
233
|
-
</div>
|
|
234
|
-
);
|
|
235
|
-
}
|
routes/index.tsx
DELETED
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import Slide from "../src/components_old/Slide.tsx";
|
|
2
|
-
import ProjectsIcon from "../src/components_old/icons/ProjectsIcon.tsx";
|
|
3
|
-
import TreeIcon from "../src/components_old/icons/TreeIcon.tsx";
|
|
4
|
-
import ContactIcon from "../src/components_old/icons/ContactIcon.tsx";
|
|
5
|
-
import HardwareIcon from "../src/components_old/icons/HardwareIcon.tsx";
|
|
6
|
-
import SoftwareIcon from "../src/components_old/icons/SoftwareIcon.tsx";
|
|
7
|
-
import GooglePlayIcon from "../src/components_old/icons/GooglePlayIcon.tsx";
|
|
8
|
-
import AppStoreIcon from "../src/components_old/icons/AppStoreIcon.tsx";
|
|
9
|
-
import { asset, Head } from "$fresh/runtime.ts";
|
|
10
|
-
|
|
11
|
-
export default function Home() {
|
|
12
|
-
return (
|
|
13
|
-
<div class="mx-auto">
|
|
14
|
-
<Head>
|
|
15
|
-
<title>pyros.sh</title>
|
|
16
|
-
<meta
|
|
17
|
-
name="description"
|
|
18
|
-
content="A fullstack developer from Bangalore who likes to create frameworks and programming languages."
|
|
19
|
-
/>
|
|
20
|
-
</Head>
|
|
21
|
-
<div class="heir-h2:text-xl heir-h2:font-bold heir-h2:middle">
|
|
22
|
-
<h1 class="text-3xl font-bold mb-4">Hello!</h1>
|
|
23
|
-
<p>
|
|
24
|
-
I{"'"}m{" "}
|
|
25
|
-
<a class="underline" href="https://www.linkedin.com/in/peter-john-in">
|
|
26
|
-
<strong>Peter John</strong>
|
|
27
|
-
</a>
|
|
28
|
-
, a fullstack developer from Bengaluru, India. I love writing code and
|
|
29
|
-
I am lucky enough to do this as my job.
|
|
30
|
-
</p>
|
|
31
|
-
<p>
|
|
32
|
-
I currently work for Equal Experts. I have a strong passion for golang
|
|
33
|
-
but I also work with react and nodejs. I{"'"}ve mostly worked with
|
|
34
|
-
startups and product based companies. I have gained a lot of domain
|
|
35
|
-
specific knowledge in healthcare and finance during these startup
|
|
36
|
-
years.
|
|
37
|
-
</p>
|
|
38
|
-
<p>
|
|
39
|
-
I like to work on open source and hobby projects. Over the course of
|
|
40
|
-
{" "}
|
|
41
|
-
{new Date().getFullYear() - 2014}{" "}
|
|
42
|
-
years I{"'"}ve accumulated a lot of useful projects used by many
|
|
43
|
-
people around the world.
|
|
44
|
-
</p>
|
|
45
|
-
<div>
|
|
46
|
-
<div class="flex items-center mt-8 mb-4 child-svg:mr-2 child-svg:text-pink-800">
|
|
47
|
-
<ProjectsIcon size="36" />
|
|
48
|
-
<h2>Projects</h2>
|
|
49
|
-
</div>
|
|
50
|
-
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-8 child-section:flex child-section:flex-col child-section:mt-4 child-section:mx-1">
|
|
51
|
-
<Slide
|
|
52
|
-
title="Rust-embed"
|
|
53
|
-
link="https://github.com/pyrossh/rust-embed"
|
|
54
|
-
>
|
|
55
|
-
<p>
|
|
56
|
-
A rust proc-macro which loads files into the rust binary at
|
|
57
|
-
compile time during release and loads the file from the fs
|
|
58
|
-
during dev
|
|
59
|
-
</p>
|
|
60
|
-
</Slide>
|
|
61
|
-
<Slide title="Gromer" link="https://github.com/pyrossh/gromer">
|
|
62
|
-
<p>
|
|
63
|
-
Gromer is a framework and cli to build web apps in golang. It
|
|
64
|
-
uses a declarative syntax using inline jsx like templates for
|
|
65
|
-
components and pages.
|
|
66
|
-
</p>
|
|
67
|
-
</Slide>
|
|
68
|
-
<Slide title="Palm" link="https://github.com/pyrossh/palm">
|
|
69
|
-
<p>
|
|
70
|
-
A programming language with a syntax largely inspired by gleam
|
|
71
|
-
and pyret but with the simplicity of go.
|
|
72
|
-
</p>
|
|
73
|
-
<p>WIP to support compilation to WASM with C-FFI support.</p>
|
|
74
|
-
</Slide>
|
|
75
|
-
<Slide
|
|
76
|
-
title="Only Bible App"
|
|
77
|
-
link="https://github.com/pyrossh/only-bible-app"
|
|
78
|
-
>
|
|
79
|
-
<p>
|
|
80
|
-
The only bible app you will ever need. No ads, No in-app
|
|
81
|
-
purchases, No distractions.
|
|
82
|
-
</p>
|
|
83
|
-
<div class="flex mt-4">
|
|
84
|
-
<a
|
|
85
|
-
class="mr-4"
|
|
86
|
-
href="https://play.google.com/store/apps/details?id=sh.pyros.only_bible_app"
|
|
87
|
-
rel="noopener noreferrer"
|
|
88
|
-
target="blank"
|
|
89
|
-
>
|
|
90
|
-
<GooglePlayIcon />
|
|
91
|
-
</a>
|
|
92
|
-
<a
|
|
93
|
-
href="https://apps.apple.com/us/app/only-bible-app/id6467606465"
|
|
94
|
-
rel="noopener noreferrer"
|
|
95
|
-
target="blank"
|
|
96
|
-
>
|
|
97
|
-
<AppStoreIcon />
|
|
98
|
-
</a>
|
|
99
|
-
</div>
|
|
100
|
-
</Slide>
|
|
101
|
-
<section>
|
|
102
|
-
<div class="flex items-center child-svg:mr-2 child-svg:text-green-800">
|
|
103
|
-
<HardwareIcon size="32" />
|
|
104
|
-
<h2>Hardware</h2>
|
|
105
|
-
</div>
|
|
106
|
-
<ul class="grid gap-2 grid-cols-1 text-center mt-4 heir-a:text-blue-900 child:bg-gray-200 child:p-1">
|
|
107
|
-
<li>M2 Macbook Air</li>
|
|
108
|
-
<li>Raspberry Pi 4B</li>
|
|
109
|
-
<li>Raspberry Pi Zero 2W</li>
|
|
110
|
-
</ul>
|
|
111
|
-
</section>
|
|
112
|
-
<section>
|
|
113
|
-
<div class="flex items-center child-svg:mr-2 child-svg:text-blue-800">
|
|
114
|
-
<SoftwareIcon size="32" />
|
|
115
|
-
<h2>Software</h2>
|
|
116
|
-
</div>
|
|
117
|
-
<ul class="grid gap-2 grid-cols-3 text-center mt-4 heir-img:w-12 heir-a:text-base heir-a:text-blue-900 heir-a:flex heir-a:flex-col heir-a:items-center child:bg-gray-200 child:p-2 child:pb-4">
|
|
118
|
-
<li>
|
|
119
|
-
<a
|
|
120
|
-
href="https://github.com/exelban/stats"
|
|
121
|
-
target="_blank"
|
|
122
|
-
rel="noopener noreferrer"
|
|
123
|
-
>
|
|
124
|
-
Stats
|
|
125
|
-
<img src={asset("/logos/stats.png")} />
|
|
126
|
-
</a>
|
|
127
|
-
</li>
|
|
128
|
-
<li>
|
|
129
|
-
<a
|
|
130
|
-
href="https://github.com/brave/brave-browser"
|
|
131
|
-
target="_blank"
|
|
132
|
-
rel="noopener noreferrer"
|
|
133
|
-
>
|
|
134
|
-
Brave
|
|
135
|
-
<img src={asset("/logos/brave.png")} />
|
|
136
|
-
</a>
|
|
137
|
-
</li>
|
|
138
|
-
<li>
|
|
139
|
-
<a
|
|
140
|
-
href="https://github.com/microsoft/vscode"
|
|
141
|
-
target="_blank"
|
|
142
|
-
rel="noopener noreferrer"
|
|
143
|
-
>
|
|
144
|
-
VS Code
|
|
145
|
-
<img src={asset("/logos/code.png")} />
|
|
146
|
-
</a>
|
|
147
|
-
</li>
|
|
148
|
-
<li>
|
|
149
|
-
<a
|
|
150
|
-
href="https://github.com/helix-editor/helix"
|
|
151
|
-
target="_blank"
|
|
152
|
-
rel="noopener noreferrer"
|
|
153
|
-
>
|
|
154
|
-
Helix
|
|
155
|
-
<img src={asset("/logos/helix.png")} />
|
|
156
|
-
</a>
|
|
157
|
-
</li>
|
|
158
|
-
<li>
|
|
159
|
-
<a
|
|
160
|
-
href="https://github.com/fish-shell/fish-shell"
|
|
161
|
-
target="_blank"
|
|
162
|
-
rel="noopener noreferrer"
|
|
163
|
-
>
|
|
164
|
-
Fish
|
|
165
|
-
<img src={asset("/logos/fish.png")} />
|
|
166
|
-
</a>
|
|
167
|
-
</li>
|
|
168
|
-
<li>
|
|
169
|
-
<a
|
|
170
|
-
href="https://github.com/gnachman/iTerm2"
|
|
171
|
-
target="_blank"
|
|
172
|
-
rel="noopener noreferrer"
|
|
173
|
-
>
|
|
174
|
-
iTerm2
|
|
175
|
-
<img src={asset("/logos/iterm.png")} />
|
|
176
|
-
</a>
|
|
177
|
-
</li>
|
|
178
|
-
<li>
|
|
179
|
-
<a
|
|
180
|
-
href="https://colorslurp.com"
|
|
181
|
-
target="_blank"
|
|
182
|
-
rel="noopener noreferrer"
|
|
183
|
-
>
|
|
184
|
-
Slurp
|
|
185
|
-
<img class="w-12" src={asset("/logos/slurp.png")} />
|
|
186
|
-
</a>
|
|
187
|
-
</li>
|
|
188
|
-
<li>
|
|
189
|
-
<a
|
|
190
|
-
href="https://www.vectornator.io"
|
|
191
|
-
target="_blank"
|
|
192
|
-
rel="noopener noreferrer"
|
|
193
|
-
>
|
|
194
|
-
Curve
|
|
195
|
-
<img class="w-12" src={asset("/logos/curve.png")} />
|
|
196
|
-
</a>
|
|
197
|
-
</li>
|
|
198
|
-
</ul>
|
|
199
|
-
</section>
|
|
200
|
-
<section>
|
|
201
|
-
<div class="flex items-center child-svg:mr-2 child-svg:text-amber-900">
|
|
202
|
-
<TreeIcon size="36" />
|
|
203
|
-
<h2>Interests</h2>
|
|
204
|
-
</div>
|
|
205
|
-
<ul class="grid gap-2 grid-cols-3 text-center mt-4 child:bg-slate-100 child:p-1">
|
|
206
|
-
<li>HTML</li>
|
|
207
|
-
<li>CSS</li>
|
|
208
|
-
<li>Tailwind</li>
|
|
209
|
-
<li>Javascript</li>
|
|
210
|
-
<li>React</li>
|
|
211
|
-
<li>Flutter</li>
|
|
212
|
-
<li>Go</li>
|
|
213
|
-
<li>Rust</li>
|
|
214
|
-
<li>Kotlin</li>
|
|
215
|
-
<li>Firestore</li>
|
|
216
|
-
<li>Kubernetes</li>
|
|
217
|
-
<li>Istio</li>
|
|
218
|
-
</ul>
|
|
219
|
-
</section>
|
|
220
|
-
<section>
|
|
221
|
-
<div class="flex items-center child-svg:mr-2 child-svg:text-cyan-950">
|
|
222
|
-
<ContactIcon size="36" />
|
|
223
|
-
<h2>Contact</h2>
|
|
224
|
-
</div>
|
|
225
|
-
<ul class="grid gap-2 grid-cols-1 text-lg text-left mt-4 heir-strong:mr-2 child:bg-slate-100 child:p-2 child:flex child:flex-col child:sm:flex-row">
|
|
226
|
-
<li>
|
|
227
|
-
<strong>Email:</strong>
|
|
228
|
-
<span>pyros2097@gmail.com</span>
|
|
229
|
-
</li>
|
|
230
|
-
<li>
|
|
231
|
-
<strong>Github:</strong>
|
|
232
|
-
<a class="text-blue-900" href="https://github.com/pyrossh">
|
|
233
|
-
https://github.com/pyrossh
|
|
234
|
-
</a>
|
|
235
|
-
</li>
|
|
236
|
-
<li>
|
|
237
|
-
<strong>LinkedIn:</strong>
|
|
238
|
-
<a
|
|
239
|
-
class="text-blue-900"
|
|
240
|
-
href="https://www.linkedin.com/in/peter-john-in"
|
|
241
|
-
>
|
|
242
|
-
https://www.linkedin.com/in/pyrossh
|
|
243
|
-
</a>
|
|
244
|
-
</li>
|
|
245
|
-
</ul>
|
|
246
|
-
</section>
|
|
247
|
-
</div>
|
|
248
|
-
</div>
|
|
249
|
-
</div>
|
|
250
|
-
</div>
|
|
251
|
-
);
|
|
252
|
-
}
|
routes/posts.tsx
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { Head } from "$fresh/runtime.ts";
|
|
2
|
-
|
|
3
|
-
// const files = await Astro.glob("./**/*.{md,mdx}");
|
|
4
|
-
// const posts = files.map(({ frontmatter: item }) => ({
|
|
5
|
-
// id: item.title.toLowerCase().replaceAll(" ", "-"),
|
|
6
|
-
// title: item.title,
|
|
7
|
-
// date: new Date(item.date),
|
|
8
|
-
// }));
|
|
9
|
-
// ---
|
|
10
|
-
|
|
11
|
-
// <style>
|
|
12
|
-
// .container {
|
|
13
|
-
// display: flex;
|
|
14
|
-
// flex-direction: column;
|
|
15
|
-
// min-height: calc(100vh - 120px);
|
|
16
|
-
// }
|
|
17
|
-
|
|
18
|
-
// .row {
|
|
19
|
-
// display: flex;
|
|
20
|
-
// flex-direction: row;
|
|
21
|
-
// align-items: center;
|
|
22
|
-
// margin-top: 1.5rem;
|
|
23
|
-
// line-height: 1.5rem;
|
|
24
|
-
|
|
25
|
-
// & span {
|
|
26
|
-
// width: 9rem;
|
|
27
|
-
// }
|
|
28
|
-
|
|
29
|
-
// & a {
|
|
30
|
-
// margin-left: 2rem;
|
|
31
|
-
// text-decoration: none;
|
|
32
|
-
// color: black;
|
|
33
|
-
// border-bottom: 2px solid black;
|
|
34
|
-
|
|
35
|
-
// &:hover,
|
|
36
|
-
// &:visited {
|
|
37
|
-
// text-decoration: none;
|
|
38
|
-
// }
|
|
39
|
-
|
|
40
|
-
// @media (--mobile) {
|
|
41
|
-
// margin-left: 0rem;
|
|
42
|
-
// }
|
|
43
|
-
// }
|
|
44
|
-
// }
|
|
45
|
-
// </style>
|
|
46
|
-
|
|
47
|
-
export default function Posts() {
|
|
48
|
-
return (
|
|
49
|
-
<div class="mx-auto">
|
|
50
|
-
<Head>
|
|
51
|
-
<title>pyros.sh | Posts</title>
|
|
52
|
-
<meta name="description" content="Peter John's Posts" />
|
|
53
|
-
</Head>
|
|
54
|
-
<div class="px-4 py-40 mx-auto">TBD</div>
|
|
55
|
-
{
|
|
56
|
-
/* <div slot="body" class="container">
|
|
57
|
-
{
|
|
58
|
-
posts.map((post) => (
|
|
59
|
-
<div class="row">
|
|
60
|
-
<span>{post.date.toISOString().split("T")[0]}</span>
|
|
61
|
-
<a href={`/blog/${post.date.getFullYear()}/${post.id}`}>
|
|
62
|
-
{post.title}
|
|
63
|
-
</a>
|
|
64
|
-
</div>
|
|
65
|
-
))
|
|
66
|
-
}
|
|
67
|
-
</div> */
|
|
68
|
-
}
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// ---
|
|
74
|
-
// const { title, description, image, date, tags } = Astro.props.frontmatter;
|
|
75
|
-
// ---
|
|
76
|
-
|
|
77
|
-
// <title slot="head">pyros.sh | {title}</title>
|
|
78
|
-
// <meta slot="head" name="description" content={description} />
|
|
79
|
-
// <meta slot="head" name="keywords" content={tags} />
|
|
80
|
-
// <div slot="body" class="post-page">
|
|
81
|
-
// <div class="title-container">
|
|
82
|
-
// <div>
|
|
83
|
-
// <h1>{title}</h1>
|
|
84
|
-
// <h2>{description}</h2>
|
|
85
|
-
// </div>
|
|
86
|
-
// <div class="date">
|
|
87
|
-
// <h3>{date}</h3>
|
|
88
|
-
// </div>
|
|
89
|
-
// </div>
|
|
90
|
-
// <div class="tags-container">
|
|
91
|
-
// {tags.map((text) => <Tag text={text} />)}
|
|
92
|
-
// </div>
|
|
93
|
-
// <div>
|
|
94
|
-
// <slot />
|
|
95
|
-
// </div>
|
|
96
|
-
// </div>
|
routes/stats.tsx
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Head } from "$fresh/runtime.ts";
|
|
2
|
-
import { Handlers, PageProps } from "$fresh/server.ts";
|
|
3
|
-
import List from "../components/List.tsx";
|
|
4
|
-
import Tile from "../components/Tile.tsx";
|
|
5
|
-
import { AnalyticsData, getAnalyticsData } from "../services/analytics.ts";
|
|
6
|
-
|
|
7
|
-
export const handler: Handlers<AnalyticsData> = {
|
|
8
|
-
async GET(_req, ctx) {
|
|
9
|
-
const data = await getAnalyticsData();
|
|
10
|
-
return ctx.render(data);
|
|
11
|
-
},
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default function Stats({ data }: PageProps<AnalyticsData>) {
|
|
15
|
-
return (
|
|
16
|
-
<>
|
|
17
|
-
<Head>
|
|
18
|
-
<title>pyros.sh | Stats</title>
|
|
19
|
-
<meta name="description" content="Analytics of the pyros.sh website" />
|
|
20
|
-
</Head>
|
|
21
|
-
<div class="flex flex-1 flex-col theme-light">
|
|
22
|
-
<div class="py-4 text-lg font-medium text-gray-800">Dashboard</div>
|
|
23
|
-
<div class="charts no-select hidden">
|
|
24
|
-
<div class="headline">
|
|
25
|
-
<div class="metrics">
|
|
26
|
-
<Tile title="Unique Visitors" value={data.vistors.toString()} />
|
|
27
|
-
<Tile title="Page Views" value={data.views.toString()} />
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
<div class="grid grid-cols-2 gap-8">
|
|
32
|
-
<List title="Pages" entries={data.pages} />
|
|
33
|
-
<List title="Countries" entries={data.countries} flag />
|
|
34
|
-
</div>
|
|
35
|
-
<div class="grid grid-cols-2 gap-8 mt-8">
|
|
36
|
-
<List title="OS" entries={data.os} />
|
|
37
|
-
<List title="Browsers" entries={data.browsers} />
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
</>
|
|
41
|
-
);
|
|
42
|
-
}
|
scripts/makePdf.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// import { launch } from "https://deno.land/x/astral/mod.ts";
|
|
2
|
-
|
|
3
|
-
// const browser = await launch({ headless: true });
|
|
4
|
-
// const page = await browser.newPage("http://localhost:8000/cv");
|
|
5
|
-
// const screenshot = await page.pdf();
|
|
6
|
-
// Deno.writeFileSync("cv.pdf", screenshot);
|
|
7
|
-
// await browser.close();
|
|
8
|
-
|
|
9
|
-
// const kv = await Deno.openKv(
|
|
10
|
-
// "https://api.deno.com/databases/07a4395a-f4e2-47cf-8d2a-9a62382193fc/connect",
|
|
11
|
-
// );
|
|
12
|
-
|
|
13
|
-
// const entries = kv.list({
|
|
14
|
-
// prefix: ["analytics"],
|
|
15
|
-
// });
|
|
16
|
-
|
|
17
|
-
// for await (const entry of entries) {
|
|
18
|
-
// await kv.delete(entry.key);
|
|
19
|
-
// }
|
src/app.html
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
-
|
|
4
|
+
<title>pyros.sh</title>
|
|
5
5
|
<meta charset="utf-8" />
|
|
6
6
|
<link rel="icon" type="image/png" href="%sveltekit.assets%/favicon.png" />
|
|
7
|
-
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
|
-
<meta name="author" content="pyrossh" />
|
|
9
|
-
<meta name="keywords" content="pyros.sh,pyrossh,astro,website" />
|
|
10
|
-
|
|
8
|
+
%unocss-svelte-scoped.global% %sveltekit.head%
|
|
11
|
-
%sveltekit.head%
|
|
12
9
|
</head>
|
|
13
10
|
<body data-sveltekit-preload-data="hover">
|
|
14
|
-
|
|
11
|
+
%sveltekit.body%
|
|
15
12
|
</body>
|
|
16
|
-
</html>
|
|
13
|
+
</html>
|
src/error.html
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
-
%unocss-svelte-scoped.global%
|
|
8
|
-
%sveltekit.head%
|
|
9
|
-
</head>
|
|
10
|
-
<body data-sveltekit-preload-data="hover">
|
|
11
|
-
<div style="display: contents">
|
|
12
|
-
%sveltekit.body%
|
|
13
|
-
|
|
14
|
-
%sveltekit.status%
|
|
15
|
-
|
|
16
|
-
%sveltekit.error.message%
|
|
17
|
-
</div>
|
|
18
|
-
</body>
|
|
19
|
-
</html>
|
src/lib/components/Footer.svelte
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
<SocialLinks />
|
|
9
9
|
</div>
|
|
10
10
|
<div class="flex">
|
|
11
|
-
<span class="text-base text-#
|
|
11
|
+
<span class="text-base text-#8D8D93 hover:no-underline"> powered by </span>
|
|
12
|
-
<a class="mx-2 -mt-3" href="https://
|
|
12
|
+
<a class="mx-2 -mt-3" href="https://kit.svelte.dev" target="_blank" rel="noopener noreferrer">
|
|
13
|
-
<
|
|
13
|
+
<div class="i-logos:svelte-kit w-24 h-12"></div>
|
|
14
14
|
</a>
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
src/lib/components/Slide.svelte
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
target="_blank"
|
|
12
12
|
rel="noopener noreferrer"
|
|
13
13
|
>
|
|
14
|
-
<div class="i-mdi-github
|
|
14
|
+
<div class="i-mdi-github mr-2" />
|
|
15
15
|
<p>{title}</p>
|
|
16
16
|
</a>
|
|
17
17
|
{@render children()}
|
src/lib/index.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
// place files you want to import through the `$lib` alias in this folder.
|
|
2
|
-
import "virtual:uno.css";
|
|
3
|
-
import "@unocss/reset/normalize.css";
|
src/routes/+error.svelte
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { page } from '$app/stores';
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<svelte:head>
|
|
6
|
+
<title>pyros.sh | {$page.error?.message}</title>
|
|
7
|
+
<meta name="description" content="${$page.error?.message}" />
|
|
8
|
+
</svelte:head>
|
|
9
|
+
|
|
10
|
+
<div class="px-4 mx-auto h-screen">
|
|
11
|
+
<div class="max-w-screen-md mx-auto flex flex-col items-center justify-center">
|
|
12
|
+
<img
|
|
13
|
+
class="my-6"
|
|
14
|
+
src="/favicon.png"
|
|
15
|
+
width="128"
|
|
16
|
+
height="128"
|
|
17
|
+
alt="the Fresh logo: a sliced lemon dripping with juice"
|
|
18
|
+
/>
|
|
19
|
+
<h1 class="text-4xl font-bold">{$page.status} - {$page.error?.message}</h1>
|
|
20
|
+
<p class="my-4">
|
|
21
|
+
{#if $page.status === 404}
|
|
22
|
+
The page you were looking for doesn't exist.
|
|
23
|
+
{:else}
|
|
24
|
+
Something went wrong. Please try again later.
|
|
25
|
+
{/if}
|
|
26
|
+
</p>
|
|
27
|
+
<a href="/" class="underline mt-4"> Go back home </a>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
src/routes/+layout.svelte
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { page } from '$app/stores';
|
|
2
3
|
import Footer from '$lib/components/Footer.svelte';
|
|
3
4
|
import Header from '$lib/components/Header.svelte';
|
|
4
5
|
let { children } = $props();
|
|
6
|
+
|
|
7
|
+
export const prerender = true;
|
|
5
8
|
</script>
|
|
6
9
|
|
|
7
10
|
<svelte:head>
|
|
11
|
+
<meta name="author" content="pyrossh" />
|
|
12
|
+
<meta name="keywords" content="pyros.sh,pyrossh,astro,website" />
|
|
13
|
+
<link rel="canonical" href={$page.url.pathname} />
|
|
8
14
|
<meta property="og:site_name" content="pyros.sh" />
|
|
9
15
|
<meta property="og:type" content="website" />
|
|
10
|
-
<!-- <link rel="canonical" href={url.toString()} />
|
|
11
|
-
|
|
16
|
+
<meta property="og:url" content={$page.url.pathname} />
|
|
12
17
|
</svelte:head>
|
|
13
18
|
<div
|
|
14
19
|
style="display: contents"
|
src/routes/+page.svelte
CHANGED
|
@@ -10,17 +10,20 @@
|
|
|
10
10
|
import curve from '$lib/assets/logos/curve.png';
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
|
-
<
|
|
13
|
+
<svelte:head>
|
|
14
14
|
<title>pyros.sh</title>
|
|
15
15
|
<meta
|
|
16
16
|
name="description"
|
|
17
17
|
content="A fullstack developer from Bangalore who likes to create frameworks and programming languages."
|
|
18
18
|
/>
|
|
19
|
+
</svelte:head>
|
|
20
|
+
|
|
21
|
+
<div class="mx-auto">
|
|
19
22
|
<div>
|
|
20
23
|
<h1 class="text-3xl font-bold mb-4">Hello!</h1>
|
|
21
24
|
<p>
|
|
22
25
|
I{"'"}m{' '}
|
|
23
|
-
<a class="underline" href="https://www.linkedin.com/in/
|
|
26
|
+
<a class="underline" href="https://www.linkedin.com/in/pyrossh">
|
|
24
27
|
<strong>Peter John</strong>
|
|
25
28
|
</a>
|
|
26
29
|
, a fullstack developer from Bengaluru, India. I love writing code and I am lucky enough to do
|
|
@@ -40,7 +43,7 @@
|
|
|
40
43
|
</p>
|
|
41
44
|
<div>
|
|
42
45
|
<div class="flex items-center mt-8 mb-4">
|
|
43
|
-
<div class="i-ic-outline-space-dashboard text-pink-800
|
|
46
|
+
<div class="i-ic-outline-space-dashboard text-pink-800 mr-2" />
|
|
44
47
|
<h2>Projects</h2>
|
|
45
48
|
</div>
|
|
46
49
|
<div
|
|
@@ -82,102 +85,118 @@
|
|
|
82
85
|
</div>
|
|
83
86
|
</Slide>
|
|
84
87
|
<section>
|
|
88
|
+
<div class="flex items-center">
|
|
85
|
-
|
|
89
|
+
<div class="i-eos-icons:hardware-circuit text-green-800 mr-2" />
|
|
86
|
-
<!-- <HardwareIcon size="32" /> -->
|
|
87
90
|
<h2>Hardware</h2>
|
|
88
91
|
</div>
|
|
89
|
-
<ul
|
|
90
|
-
|
|
92
|
+
<ul class="grid gap-2 grid-cols-1 text-center mt-4 children:(bg-gray-200 p-1)">
|
|
91
|
-
>
|
|
92
93
|
<li>M2 Macbook Air</li>
|
|
93
94
|
<li>Raspberry Pi 4B</li>
|
|
94
95
|
<li>Raspberry Pi Zero 2W</li>
|
|
95
96
|
</ul>
|
|
96
97
|
</section>
|
|
97
98
|
<section>
|
|
99
|
+
<div class="flex items-center">
|
|
98
|
-
|
|
100
|
+
<div class="i-eos-icons:software-outlined text-blue-800 mr-2" />
|
|
99
|
-
<!-- <SoftwareIcon size="32" /> -->
|
|
100
101
|
<h2>Software</h2>
|
|
101
102
|
</div>
|
|
102
|
-
<ul
|
|
103
|
-
|
|
103
|
+
<ul class="grid gap-2 grid-cols-3 text-center mt-4 children:(bg-gray-200 p-2 pb-4)">
|
|
104
|
-
>
|
|
105
104
|
<li>
|
|
105
|
+
<a
|
|
106
|
+
class="soft-link"
|
|
106
|
-
|
|
107
|
+
href="https://github.com/exelban/stats"
|
|
108
|
+
target="_blank"
|
|
109
|
+
rel="noopener noreferrer"
|
|
110
|
+
>
|
|
107
111
|
Stats
|
|
108
|
-
<img class="
|
|
112
|
+
<img class="soft-icon" src={stats} alt="Stats" />
|
|
109
113
|
</a>
|
|
110
114
|
</li>
|
|
111
115
|
<li>
|
|
112
116
|
<a
|
|
117
|
+
class="soft-link"
|
|
113
118
|
href="https://github.com/brave/brave-browser"
|
|
114
119
|
target="_blank"
|
|
115
120
|
rel="noopener noreferrer"
|
|
116
121
|
>
|
|
117
122
|
Brave
|
|
118
|
-
<img class="
|
|
123
|
+
<img class="soft-icon" src={brave} alt="Brave" />
|
|
119
124
|
</a>
|
|
120
125
|
</li>
|
|
121
126
|
<li>
|
|
122
127
|
<a
|
|
128
|
+
class="soft-link"
|
|
123
129
|
href="https://github.com/microsoft/vscode"
|
|
124
130
|
target="_blank"
|
|
125
131
|
rel="noopener noreferrer"
|
|
126
132
|
>
|
|
127
133
|
VS Code
|
|
128
|
-
<img class="
|
|
134
|
+
<img class="soft-icon" src={code} alt="VsCode" />
|
|
129
135
|
</a>
|
|
130
136
|
</li>
|
|
131
137
|
<li>
|
|
132
138
|
<a
|
|
139
|
+
class="soft-link"
|
|
133
140
|
href="https://github.com/helix-editor/helix"
|
|
134
141
|
target="_blank"
|
|
135
142
|
rel="noopener noreferrer"
|
|
136
143
|
>
|
|
137
144
|
Helix
|
|
138
|
-
<img class="
|
|
145
|
+
<img class="soft-icon" src={helix} alt="Helix" />
|
|
139
146
|
</a>
|
|
140
147
|
</li>
|
|
141
148
|
<li>
|
|
142
149
|
<a
|
|
150
|
+
class="soft-link"
|
|
143
151
|
href="https://github.com/fish-shell/fish-shell"
|
|
144
152
|
target="_blank"
|
|
145
153
|
rel="noopener noreferrer"
|
|
146
154
|
>
|
|
147
155
|
Fish
|
|
148
|
-
<img class="
|
|
156
|
+
<img class="soft-icon" src={fish} alt="Fish" />
|
|
149
157
|
</a>
|
|
150
158
|
</li>
|
|
151
159
|
<li>
|
|
152
160
|
<a
|
|
161
|
+
class="soft-link"
|
|
153
162
|
href="https://github.com/gnachman/iTerm2"
|
|
154
163
|
target="_blank"
|
|
155
164
|
rel="noopener noreferrer"
|
|
156
165
|
>
|
|
157
166
|
iTerm2
|
|
158
|
-
<img class="
|
|
167
|
+
<img class="soft-icon" src={iterm} alt="iterm2" />
|
|
159
168
|
</a>
|
|
160
169
|
</li>
|
|
161
170
|
<li>
|
|
171
|
+
<a
|
|
172
|
+
class="soft-link"
|
|
162
|
-
|
|
173
|
+
href="https://colorslurp.com"
|
|
174
|
+
target="_blank"
|
|
175
|
+
rel="noopener noreferrer"
|
|
176
|
+
>
|
|
163
177
|
Slurp
|
|
164
|
-
<img class="
|
|
178
|
+
<img class="soft-icon" src={slurp} alt="slurp" />
|
|
165
179
|
</a>
|
|
166
180
|
</li>
|
|
167
181
|
<li>
|
|
182
|
+
<a
|
|
183
|
+
class="soft-link"
|
|
168
|
-
|
|
184
|
+
href="https://www.vectornator.io"
|
|
185
|
+
target="_blank"
|
|
186
|
+
rel="noopener noreferrer"
|
|
187
|
+
>
|
|
169
188
|
Curve
|
|
170
|
-
<img class="
|
|
189
|
+
<img class="soft-icon" src={curve} alt="curve" />
|
|
171
190
|
</a>
|
|
172
191
|
</li>
|
|
173
192
|
</ul>
|
|
174
193
|
</section>
|
|
175
194
|
<section>
|
|
195
|
+
<div class="flex items-center">
|
|
176
|
-
|
|
196
|
+
<div class="i-mdi:file-tree-outline text-amber-900 mr-2" />
|
|
177
|
-
<!-- <TreeIcon size="36" /> -->
|
|
178
197
|
<h2>Interests</h2>
|
|
179
198
|
</div>
|
|
180
|
-
<ul class="grid gap-2 grid-cols-3 text-center mt-4
|
|
199
|
+
<ul class="grid gap-2 grid-cols-3 text-center mt-4 children:(bg-slate-100 p-1)">
|
|
181
200
|
<li>HTML</li>
|
|
182
201
|
<li>CSS</li>
|
|
183
202
|
<li>Tailwind</li>
|
|
@@ -193,25 +212,25 @@
|
|
|
193
212
|
</ul>
|
|
194
213
|
</section>
|
|
195
214
|
<section>
|
|
215
|
+
<div class="flex items-center">
|
|
196
|
-
|
|
216
|
+
<div class="i-mdi-contact-outline text-cyan-950 mr-2" />
|
|
197
|
-
<!-- <ContactIcon size="36" /> -->
|
|
198
217
|
<h2>Contact</h2>
|
|
199
218
|
</div>
|
|
200
219
|
<ul
|
|
201
|
-
class="grid gap-2 grid-cols-1 text-lg text-left mt-4
|
|
220
|
+
class="grid gap-2 grid-cols-1 text-lg text-left mt-4 children:(bg-slate-100 p-2 flex flex-col sm:flex-row)"
|
|
202
221
|
>
|
|
203
222
|
<li>
|
|
204
|
-
<strong>Email:</strong>
|
|
223
|
+
<strong class="mr-2">Email:</strong>
|
|
205
224
|
<span>pyros2097@gmail.com</span>
|
|
206
225
|
</li>
|
|
207
226
|
<li>
|
|
208
|
-
<strong>Github:</strong>
|
|
227
|
+
<strong class="mr-2">Github:</strong>
|
|
209
228
|
<a class="text-blue-900" href="https://github.com/pyrossh">
|
|
210
229
|
https://github.com/pyrossh
|
|
211
230
|
</a>
|
|
212
231
|
</li>
|
|
213
232
|
<li>
|
|
214
|
-
<strong>LinkedIn:</strong>
|
|
233
|
+
<strong class="mr-2">LinkedIn:</strong>
|
|
215
234
|
<a class="text-blue-900" href="https://www.linkedin.com/in/peter-john-in">
|
|
216
235
|
https://www.linkedin.com/in/pyrossh
|
|
217
236
|
</a>
|
|
@@ -227,4 +246,12 @@
|
|
|
227
246
|
h2 {
|
|
228
247
|
--at-apply: text-xl font-semibold middle;
|
|
229
248
|
}
|
|
249
|
+
|
|
250
|
+
.soft-link {
|
|
251
|
+
--at-apply: text-base text-blue-900 flex flex-col items-center;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.soft-icon {
|
|
255
|
+
--at-apply: w-12 h-12;
|
|
256
|
+
}
|
|
230
257
|
</style>
|
src/routes/cv/+page.svelte
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
<svelte:head>
|
|
2
|
+
<title>pyros.sh | CV</title>
|
|
3
|
+
<meta name="description" content="Peter John's CV" />
|
|
4
|
+
</svelte:head>
|
|
5
|
+
|
|
6
|
+
<div>
|
|
7
|
+
<section>
|
|
8
|
+
<h3>Equal Experts</h3>
|
|
9
|
+
<h4>Software Developer, Oct 2018 - present</h4>
|
|
10
|
+
<h5>
|
|
11
|
+
Making Software. Better. Equal Experts is a network of talented, experienced software
|
|
12
|
+
consultants, specialising in agile delivery.
|
|
13
|
+
</h5>
|
|
14
|
+
<div>
|
|
15
|
+
These are the client projects I worked on,
|
|
16
|
+
<ul>
|
|
17
|
+
<li>
|
|
18
|
+
<b>John Lewis</b>
|
|
19
|
+
<ul>
|
|
20
|
+
<li>Built a social quiz game to improve engagement across the website</li>
|
|
21
|
+
<li>
|
|
22
|
+
Implemented new functionality in customer self serve functions like returns,
|
|
23
|
+
cancellations, tracking.
|
|
24
|
+
</li>
|
|
25
|
+
<li>
|
|
26
|
+
Refactored the old self serve reactjs app to use nextjs and removed a large redux
|
|
27
|
+
dependency thereby simplifying the codebase.
|
|
28
|
+
</li>
|
|
29
|
+
<li>
|
|
30
|
+
Ran many experiments in the customer services and order pages to improve our metrics
|
|
31
|
+
and reduce contacts.
|
|
32
|
+
</li>
|
|
33
|
+
<li>
|
|
34
|
+
Built the new Product Description Page (PDP) for Simple Carpets using a micro frontend
|
|
35
|
+
architecture.
|
|
36
|
+
</li>
|
|
37
|
+
</ul>
|
|
38
|
+
</li>
|
|
39
|
+
<li>
|
|
40
|
+
<b>iOWNA</b>
|
|
41
|
+
<ul>
|
|
42
|
+
<li>Built a content editor for curators to create content on our platform</li>
|
|
43
|
+
<li>
|
|
44
|
+
Built the iOWNA crossplatform app in react-native that works in android, ios, and web
|
|
45
|
+
using one codebase.
|
|
46
|
+
</li>
|
|
47
|
+
<li>Implemented admin specific functionalities in the web app</li>
|
|
48
|
+
<li>Implemented an in-app OTA update method using expo and semantic versionin</li>
|
|
49
|
+
<li>Built the iOWNA marketing website</li>
|
|
50
|
+
<li>
|
|
51
|
+
Built the Health Questionnaire clinician/patient feedback form feature with push
|
|
52
|
+
notifications
|
|
53
|
+
</li>
|
|
54
|
+
</ul>
|
|
55
|
+
</li>
|
|
56
|
+
<li>
|
|
57
|
+
<b>Zeta</b>
|
|
58
|
+
<ul>
|
|
59
|
+
<li>
|
|
60
|
+
Added multiple download formats (pdf,html,xlsx) for reports in the Reporting Center
|
|
61
|
+
</li>
|
|
62
|
+
<li>
|
|
63
|
+
Created a Groovy Script to automate creating ACL in sandbox authorization framework
|
|
64
|
+
</li>
|
|
65
|
+
<li>Integrated Camunda Workflow Engine into Zeta services in Operations Center</li>
|
|
66
|
+
<li>Built a few workflows on Camunda and integrated it with some internal services</li>
|
|
67
|
+
<li>
|
|
68
|
+
Built a custom k8s CRD using the operator framework to automate creating ACL in
|
|
69
|
+
sandbox using custom resources
|
|
70
|
+
</li>
|
|
71
|
+
</ul>
|
|
72
|
+
</li>
|
|
73
|
+
<li>
|
|
74
|
+
<b>Lifebox</b>
|
|
75
|
+
<ul>
|
|
76
|
+
<li>Added search functionality to the hospital procedure codes</li>
|
|
77
|
+
<li>
|
|
78
|
+
Converted the Health Questionnaire from json to native go code making it easier to
|
|
79
|
+
make changes to it
|
|
80
|
+
</li>
|
|
81
|
+
<li>
|
|
82
|
+
Integrated with SAP using HL7 message format to create patients, episodes,
|
|
83
|
+
schedule/cancel procedures
|
|
84
|
+
</li>
|
|
85
|
+
<li>Built the Patient Document repository for uploading, downloading patient files</li>
|
|
86
|
+
<li>Built the patients online reports view using the data from SAP</li>
|
|
87
|
+
</ul>
|
|
88
|
+
</li>
|
|
89
|
+
</ul>
|
|
90
|
+
</div>
|
|
91
|
+
</section>
|
|
92
|
+
<section>
|
|
93
|
+
<h3>Numberz</h3>
|
|
94
|
+
<h4>Full Stack Developer, Sept 2016 - Oct 2018</h4>
|
|
95
|
+
<h5>
|
|
96
|
+
Numberz integrates banking with your day-2-day business work-flows freeing up a lot of effort,
|
|
97
|
+
time and heart-burn, to help your business grow.
|
|
98
|
+
</h5>
|
|
99
|
+
<ul>
|
|
100
|
+
<li>Implemented new features and fixed bugs on the numberz android app</li>
|
|
101
|
+
<li>Integrated numberz with Tally ERP</li>
|
|
102
|
+
<li>
|
|
103
|
+
Implemented CI and Devops within out system to ease our deployment process using docker and
|
|
104
|
+
docker-compose
|
|
105
|
+
</li>
|
|
106
|
+
<li>
|
|
107
|
+
Created a slack bot called deploybot which was used to deploy our microservices to our
|
|
108
|
+
servers
|
|
109
|
+
</li>
|
|
110
|
+
<li>Started tech talks on Thursdays to discuss cutting edge technologies</li>
|
|
111
|
+
<li>Architected and built the Notification Service using rabbitmq and nodejs</li>
|
|
112
|
+
<li>Built the Multi-User and Multi-Company Features</li>
|
|
113
|
+
<li>
|
|
114
|
+
Implemented and lead a team on integration with the GSTN System so that customers could file
|
|
115
|
+
their GST Taxes within our product
|
|
116
|
+
</li>
|
|
117
|
+
<li>Architected and built the numberz Identity Management Service(IMS)</li>
|
|
118
|
+
<li>Architected our new product called the Numberz Accounts Receivable (AR)</li>
|
|
119
|
+
<li>Laid down the architecture for the frontend and backend</li>
|
|
120
|
+
<li>
|
|
121
|
+
Built these core features for our new AR Product - Auto Reminders, Manual Reminders, User
|
|
122
|
+
Management, Cash Discounting, CFO Dashboard Metrics
|
|
123
|
+
</li>
|
|
124
|
+
</ul>
|
|
125
|
+
</section>
|
|
126
|
+
<section>
|
|
127
|
+
<h3>Playlyfe</h3>
|
|
128
|
+
<h4>Full Stack Developer, Apr 2014 - Sept 2016</h4>
|
|
129
|
+
<h5>
|
|
130
|
+
Playlyfe is an online Gamification Platform which empowers anyone to design and implement a
|
|
131
|
+
gamified system.
|
|
132
|
+
</h5>
|
|
133
|
+
<ul>
|
|
134
|
+
<li>Built the Playlyfe Hybrid Mobile app using Phonegap for Android and iOS</li>
|
|
135
|
+
<li>Built the leaderboard system using Mongodb, Redis and Couchbase as the datastore</li>
|
|
136
|
+
<li>Migration of data from v1 to v2 of the API</li>
|
|
137
|
+
<li>Built SDKs for the Playlyfe v2 API in C#, Java, Python, Ruby, PHP, Nodejs, Gos</li>
|
|
138
|
+
<li>Maintained the job server and wrote most of the background jobs</li>
|
|
139
|
+
<li>
|
|
140
|
+
Added documentation to most of the REST API and created the Developer Console which was Like
|
|
141
|
+
Swagger UI
|
|
142
|
+
</li>
|
|
143
|
+
<li>Integrated our REST API in Leanosphere's LMS</li>
|
|
144
|
+
<li>Integrated the REST API in Knolskape's product Aktivlearn LMS</li>
|
|
145
|
+
<li>Integrated the REST API in Linkstreet's LMS</li>
|
|
146
|
+
<li>
|
|
147
|
+
Integrated the REST API in Moodle LMS by creating an admin plugin to add Gamification
|
|
148
|
+
features
|
|
149
|
+
</li>
|
|
150
|
+
<li>Rebuilt the core platform in golang for performance and developement speed</li>
|
|
151
|
+
<li>Built the GraphQL API for our cutting edge product Catalyst</li>
|
|
152
|
+
<li>Convinced the boss to create our own scripting language plscript for our rule engine.</li>
|
|
153
|
+
<li>Build a REST API for our product catalyst for a POC with Vodafone</li>
|
|
154
|
+
<li>
|
|
155
|
+
Built the Quiz, Review, Match, Tournament features in Catalyst for a major project with HP
|
|
156
|
+
</li>
|
|
157
|
+
<li>Added gamification features to Saudi Matches a popular game tracking app</li>
|
|
158
|
+
</ul>
|
|
159
|
+
</section>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<style>
|
|
163
|
+
b {
|
|
164
|
+
font-weight: 600;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
ul {
|
|
168
|
+
margin: 0.5rem;
|
|
169
|
+
padding-left: 2rem;
|
|
170
|
+
@media (--mobile) {
|
|
171
|
+
margin: 0.5rem;
|
|
172
|
+
padding-left: 1rem;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
li {
|
|
177
|
+
list-style-type: disc;
|
|
178
|
+
list-style-position: outside;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
h3 {
|
|
182
|
+
font-weight: 700;
|
|
183
|
+
font-size: 1.2rem;
|
|
184
|
+
margin-top: 0.5rem;
|
|
185
|
+
margin-bottom: 0.5rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
h4 {
|
|
189
|
+
font-weight: 500;
|
|
190
|
+
margin-top: 0.5rem;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
h5 {
|
|
194
|
+
margin-top: 0.5rem;
|
|
195
|
+
}
|
|
196
|
+
</style>
|
src/routes/posts/+page.svelte
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
<svelte:head>
|
|
2
|
+
<title>pyros.sh | Posts</title>
|
|
3
|
+
<meta name="description" content="Peter John's Posts" />
|
|
4
|
+
</svelte:head>
|
|
5
|
+
<div class="h-screen">
|
|
6
|
+
<div class="px-4 py-40 mx-auto">TBD</div>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<!--
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
// {
|
|
13
|
+
// /* <div slot="body" class="container">
|
|
14
|
+
// {
|
|
15
|
+
// posts.map((post) => (
|
|
16
|
+
// <div class="row">
|
|
17
|
+
// <span>{post.date.toISOString().split("T")[0]}</span>
|
|
18
|
+
// <a href={`/blog/${post.date.getFullYear()}/${post.id}`}>
|
|
19
|
+
// {post.title}
|
|
20
|
+
// </a>
|
|
21
|
+
// </div>
|
|
22
|
+
// ))
|
|
23
|
+
// }
|
|
24
|
+
// </div> */
|
|
25
|
+
// }
|
|
26
|
+
// ---
|
|
27
|
+
// const { title, description, image, date, tags } = Astro.props.frontmatter;
|
|
28
|
+
// ---
|
|
29
|
+
|
|
30
|
+
// <title slot="head">pyros.sh | {title}</title>
|
|
31
|
+
// <meta slot="head" name="description" content={description} />
|
|
32
|
+
// <meta slot="head" name="keywords" content={tags} />
|
|
33
|
+
// <div slot="body" class="post-page">
|
|
34
|
+
// <div class="title-container">
|
|
35
|
+
// <div>
|
|
36
|
+
// <h1>{title}</h1>
|
|
37
|
+
// <h2>{description}</h2>
|
|
38
|
+
// </div>
|
|
39
|
+
// <div class="date">
|
|
40
|
+
// <h3>{date}</h3>
|
|
41
|
+
// </div>
|
|
42
|
+
// </div>
|
|
43
|
+
// <div class="tags-container">
|
|
44
|
+
// {tags.map((text) => <Tag text={text} />)}
|
|
45
|
+
// </div>
|
|
46
|
+
// <div>
|
|
47
|
+
// <slot />
|
|
48
|
+
// </div>
|
|
49
|
+
// </div>
|
|
50
|
+
|
|
51
|
+
// const files = await Astro.glob("./**/*.{md,mdx}");
|
|
52
|
+
// const posts = files.map(({ frontmatter: item }) => ({
|
|
53
|
+
// id: item.title.toLowerCase().replaceAll(" ", "-"),
|
|
54
|
+
// title: item.title,
|
|
55
|
+
// date: new Date(item.date),
|
|
56
|
+
// }));
|
|
57
|
+
// ---
|
|
58
|
+
|
|
59
|
+
// <style>
|
|
60
|
+
// .container {
|
|
61
|
+
// display: flex;
|
|
62
|
+
// flex-direction: column;
|
|
63
|
+
// min-height: calc(100vh - 120px);
|
|
64
|
+
// }
|
|
65
|
+
|
|
66
|
+
// .row {
|
|
67
|
+
// display: flex;
|
|
68
|
+
// flex-direction: row;
|
|
69
|
+
// align-items: center;
|
|
70
|
+
// margin-top: 1.5rem;
|
|
71
|
+
// line-height: 1.5rem;
|
|
72
|
+
|
|
73
|
+
// & span {
|
|
74
|
+
// width: 9rem;
|
|
75
|
+
// }
|
|
76
|
+
|
|
77
|
+
// & a {
|
|
78
|
+
// margin-left: 2rem;
|
|
79
|
+
// text-decoration: none;
|
|
80
|
+
// color: black;
|
|
81
|
+
// border-bottom: 2px solid black;
|
|
82
|
+
|
|
83
|
+
// &:hover,
|
|
84
|
+
// &:visited {
|
|
85
|
+
// text-decoration: none;
|
|
86
|
+
// }
|
|
87
|
+
|
|
88
|
+
// @media (--mobile) {
|
|
89
|
+
// margin-left: 0rem;
|
|
90
|
+
// }
|
|
91
|
+
// }
|
|
92
|
+
// }
|
|
93
|
+
// </style>
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
-->
|
|
97
|
+
|
|
98
|
+
<style>
|
|
99
|
+
.post-page {
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-direction: column;
|
|
102
|
+
width: 100%;
|
|
103
|
+
|
|
104
|
+
& code {
|
|
105
|
+
font-family:
|
|
106
|
+
Menlo,
|
|
107
|
+
Monaco,
|
|
108
|
+
Courier New,
|
|
109
|
+
monospace;
|
|
110
|
+
font-size: 0.9em;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
& p {
|
|
114
|
+
margin-top: 1rem;
|
|
115
|
+
margin-bottom: 1rem;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
& pre {
|
|
119
|
+
max-width: 64rem;
|
|
120
|
+
font-family: monospace;
|
|
121
|
+
font-size: 14px;
|
|
122
|
+
border-radius: 16px;
|
|
123
|
+
padding: 16px;
|
|
124
|
+
margin: 8px;
|
|
125
|
+
line-height: 20px;
|
|
126
|
+
overflow-x: auto;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
& img {
|
|
130
|
+
width: auto;
|
|
131
|
+
@media (--mobile) {
|
|
132
|
+
width: 100%;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
& .title-container {
|
|
137
|
+
display: flex;
|
|
138
|
+
flex: 1;
|
|
139
|
+
font-family: serif;
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
|
|
142
|
+
& h1 {
|
|
143
|
+
color: var(--black-light);
|
|
144
|
+
margin: 0;
|
|
145
|
+
line-height: 3rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
& h2 {
|
|
149
|
+
color: var(--yellow-dark);
|
|
150
|
+
font-size: 1.5rem;
|
|
151
|
+
font-weight: 500;
|
|
152
|
+
margin-top: 20px;
|
|
153
|
+
margin-bottom: 20px;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
& h3 {
|
|
157
|
+
color: var(--black-light);
|
|
158
|
+
font-size: 1.5rem;
|
|
159
|
+
font-weight: 500;
|
|
160
|
+
margin: 0;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
& .date {
|
|
164
|
+
display: flex;
|
|
165
|
+
flex: 1;
|
|
166
|
+
flex-direction: row;
|
|
167
|
+
justify-content: flex-end;
|
|
168
|
+
margin-right: var(--space-10);
|
|
169
|
+
|
|
170
|
+
@media (--mobile) {
|
|
171
|
+
justify-content: flex-start;
|
|
172
|
+
margin-top: 0.5rem;
|
|
173
|
+
margin-bottom: 0.5rem;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
& .tags-container {
|
|
179
|
+
margin-top: var(--space-1);
|
|
180
|
+
margin-bottom: var(--space-1);
|
|
181
|
+
|
|
182
|
+
@media (--mobile) {
|
|
183
|
+
margin-top: var(--space-4);
|
|
184
|
+
margin-bottom: var(--space-4);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.tag {
|
|
190
|
+
background-color: var(--black-light);
|
|
191
|
+
color: white;
|
|
192
|
+
display: inline-block;
|
|
193
|
+
padding-left: 8px;
|
|
194
|
+
padding-right: 8px;
|
|
195
|
+
text-align: center;
|
|
196
|
+
margin-right: 1rem;
|
|
197
|
+
}
|
|
198
|
+
</style>
|
static/favicon.png
CHANGED
|
Binary file
|
{design → static}/logo.curve
RENAMED
|
File without changes
|
static/logo.svg
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
<svg width="40" height="40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<path d="M34.092 8.845C38.929 20.652 34.092 27 30 30.5c1 3.5-2.986 4.222-4.5 2.5-4.457 1.537-13.512 1.487-20-5C2 24.5 4.73 16.714 14 11.5c8-4.5 16-7 20.092-2.655Z" fill="#FFDB1E"/>
|
|
3
|
-
<path d="M14 11.5c6.848-4.497 15.025-6.38 18.368-3.47C37.5 12.5 21.5 22.612 15.5 25c-6.5 2.587-3 8.5-6.5 8.5-3 0-2.5-4-5.183-7.75C2.232 23.535 6.16 16.648 14 11.5Z" fill="#fff" stroke="#FFDB1E"/>
|
|
4
|
-
<path d="M28.535 8.772c4.645 1.25-.365 5.695-4.303 8.536-3.732 2.692-6.606 4.21-7.923 4.83-.366.173-1.617-2.252-1.617-1 0 .417-.7 2.238-.934 2.326-1.365.512-4.223 1.29-5.835 1.29-3.491 0-1.923-4.754 3.014-9.122.892-.789 1.478-.645 2.283-.645-.537-.773-.534-.917.403-1.546C17.79 10.64 23 8.77 25.212 8.42c.366.014.82.35.82.629.41-.14 2.095-.388 2.503-.278Z" fill="#FFE600"/>
|
|
5
|
-
<path d="M14.297 16.49c.985-.747 1.644-1.01 2.099-2.526.566.121.841-.08 1.29-.701.324.466 1.657.608 2.453.701-.715.451-1.057.852-1.452 2.106-1.464-.611-3.167-.302-4.39.42Z" fill="#fff"/>
|
|
6
|
-
</svg>
|
static/styles.css
DELETED
|
@@ -1,438 +0,0 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
@page {
|
|
6
|
-
size: A4;
|
|
7
|
-
margin: 0;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.post-page {
|
|
11
|
-
display: flex;
|
|
12
|
-
flex-direction: column;
|
|
13
|
-
width: 100%;
|
|
14
|
-
|
|
15
|
-
& code {
|
|
16
|
-
font-family: Menlo, Monaco, Courier New, monospace;
|
|
17
|
-
font-size: 0.9em;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
& p {
|
|
21
|
-
margin-top: 1rem;
|
|
22
|
-
margin-bottom: 1rem;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
& pre {
|
|
26
|
-
max-width: 64rem;
|
|
27
|
-
font-family: monospace;
|
|
28
|
-
font-size: 14px;
|
|
29
|
-
border-radius: 16px;
|
|
30
|
-
padding: 16px;
|
|
31
|
-
margin: 8px;
|
|
32
|
-
line-height: 20px;
|
|
33
|
-
overflow-x: auto;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
& img {
|
|
37
|
-
width: auto;
|
|
38
|
-
@media (--mobile) {
|
|
39
|
-
width: 100%;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
& .title-container {
|
|
44
|
-
display: flex;
|
|
45
|
-
flex: 1;
|
|
46
|
-
font-family: serif;
|
|
47
|
-
flex-direction: column;
|
|
48
|
-
|
|
49
|
-
& h1 {
|
|
50
|
-
color: var(--black-light);
|
|
51
|
-
margin: 0;
|
|
52
|
-
line-height: 3rem;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
& h2 {
|
|
56
|
-
color: var(--yellow-dark);
|
|
57
|
-
font-size: 1.5rem;
|
|
58
|
-
font-weight: 500;
|
|
59
|
-
margin-top: 20px;
|
|
60
|
-
margin-bottom: 20px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
& h3 {
|
|
64
|
-
color: var(--black-light);
|
|
65
|
-
font-size: 1.5rem;
|
|
66
|
-
font-weight: 500;
|
|
67
|
-
margin: 0;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
& .date {
|
|
71
|
-
display: flex;
|
|
72
|
-
flex: 1;
|
|
73
|
-
flex-direction: row;
|
|
74
|
-
justify-content: flex-end;
|
|
75
|
-
margin-right: var(--space-10);
|
|
76
|
-
|
|
77
|
-
@media (--mobile) {
|
|
78
|
-
justify-content: flex-start;
|
|
79
|
-
margin-top: 0.5rem;
|
|
80
|
-
margin-bottom: 0.5rem;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
& .tags-container {
|
|
86
|
-
margin-top: var(--space-1);
|
|
87
|
-
margin-bottom: var(--space-1);
|
|
88
|
-
|
|
89
|
-
@media (--mobile) {
|
|
90
|
-
margin-top: var(--space-4);
|
|
91
|
-
margin-bottom: var(--space-4);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.tag {
|
|
97
|
-
background-color: var(--black-light);
|
|
98
|
-
color: white;
|
|
99
|
-
display: inline-block;
|
|
100
|
-
padding-left: 8px;
|
|
101
|
-
padding-right: 8px;
|
|
102
|
-
text-align: center;
|
|
103
|
-
margin-right: 1rem;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
html {
|
|
107
|
-
--black: #000;
|
|
108
|
-
--white: #fff;
|
|
109
|
-
--beige: #f8f5ed;
|
|
110
|
-
--green: #6ece9d;
|
|
111
|
-
--yellow: #ffda6e;
|
|
112
|
-
--orange: #f7a66b;
|
|
113
|
-
--red: #e87b7b;
|
|
114
|
-
--theme-light-color-primary: var(--black);
|
|
115
|
-
--theme-light-color-background-primary: var(--beige);
|
|
116
|
-
--theme-light-color-secondary: #707070;
|
|
117
|
-
--theme-light-color-background-secondary: var(--white);
|
|
118
|
-
--theme-light-color-button: var(--black);
|
|
119
|
-
--theme-light-color-background-button: var(--green);
|
|
120
|
-
--theme-light-color-accent: var(--green);
|
|
121
|
-
--theme-light-color-green: var(--green);
|
|
122
|
-
--theme-light-color-yellow: var(--yellow);
|
|
123
|
-
--theme-light-color-orange: var(--orange);
|
|
124
|
-
--theme-light-color-red: var(--red);
|
|
125
|
-
--theme-light-color-background-elevation: rgba(0, 0, 0, 0.04);
|
|
126
|
-
--theme-light-box-shadow-primary: 0px 4px 16px rgba(0, 0, 0, 0.1);
|
|
127
|
-
--theme-light-box-shadow-secondary: none;
|
|
128
|
-
--theme-dark-color-primary: var(--white);
|
|
129
|
-
--theme-dark-color-background-primary: #0a0a0a;
|
|
130
|
-
--theme-dark-color-secondary: #adadad;
|
|
131
|
-
--theme-dark-color-background-secondary: #141414;
|
|
132
|
-
--theme-dark-color-button: var(--black);
|
|
133
|
-
--theme-dark-color-background-button: var(--green);
|
|
134
|
-
--theme-dark-color-accent: var(--green);
|
|
135
|
-
--theme-dark-color-green: var(--green);
|
|
136
|
-
--theme-dark-color-yellow: var(--yellow);
|
|
137
|
-
--theme-dark-color-orange: var(--orange);
|
|
138
|
-
--theme-dark-color-red: var(--red);
|
|
139
|
-
--theme-dark-color-background-elevation: rgba(255, 255, 255, 0.04);
|
|
140
|
-
--theme-dark-box-shadow-primary: 0px 4px 16px rgba(0, 0, 0, 0.8);
|
|
141
|
-
--theme-dark-box-shadow-secondary: none;
|
|
142
|
-
--theme-border-radius-primary: 12px;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.theme-light {
|
|
146
|
-
color-scheme: light;
|
|
147
|
-
--color-primary: var(--theme-light-color-primary);
|
|
148
|
-
--color-background-primary: var(--theme-light-color-background-primary);
|
|
149
|
-
--color-secondary: var(--theme-light-color-secondary);
|
|
150
|
-
--color-background-secondary: var(--theme-light-color-background-secondary);
|
|
151
|
-
--color-button: var(--theme-light-color-button);
|
|
152
|
-
--color-background-button: var(--theme-light-color-background-button);
|
|
153
|
-
--color-accent: var(--theme-light-color-accent);
|
|
154
|
-
--color-green: var(--theme-light-color-green);
|
|
155
|
-
--color-yellow: var(--theme-light-color-yellow);
|
|
156
|
-
--color-orange: var(--theme-light-color-orange);
|
|
157
|
-
--color-red: var(--theme-light-color-red);
|
|
158
|
-
--color-background-elevation: var(--theme-light-color-background-elevation);
|
|
159
|
-
--box-shadow-primary: var(--theme-light-box-shadow-primary);
|
|
160
|
-
--box-shadow-secondary: var(--theme-light-box-shadow-secondary);
|
|
161
|
-
--border-radius-primary: var(--theme-border-radius-primary);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
.theme-dark {
|
|
165
|
-
color-scheme: dark;
|
|
166
|
-
--color-primary: var(--theme-dark-color-primary);
|
|
167
|
-
--color-background-primary: var(--theme-dark-color-background-primary);
|
|
168
|
-
--color-secondary: var(--theme-dark-color-secondary);
|
|
169
|
-
--color-background-secondary: var(--theme-dark-color-background-secondary);
|
|
170
|
-
--color-button: var(--theme-dark-color-button);
|
|
171
|
-
--color-background-button: var(--theme-dark-color-background-button);
|
|
172
|
-
--color-accent: var(--theme-dark-color-accent);
|
|
173
|
-
--color-green: var(--theme-dark-color-green);
|
|
174
|
-
--color-yellow: var(--theme-dark-color-yellow);
|
|
175
|
-
--color-orange: var(--theme-dark-color-orange);
|
|
176
|
-
--color-red: var(--theme-dark-color-red);
|
|
177
|
-
--color-background-elevation: var(--theme-dark-color-background-elevation);
|
|
178
|
-
--box-shadow-primary: var(--theme-dark-box-shadow-primary);
|
|
179
|
-
--box-shadow-secondary: var(--theme-dark-box-shadow-secondary);
|
|
180
|
-
--border-radius-primary: var(--theme-border-radius-primary);
|
|
181
|
-
--img-filter: saturate(0.8) brightness(1.2);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
.charts {
|
|
185
|
-
position: relative;
|
|
186
|
-
display: flex;
|
|
187
|
-
flex-direction: column;
|
|
188
|
-
gap: 12px;
|
|
189
|
-
margin: 8px 0 16px;
|
|
190
|
-
padding: 24px 24px 16px;
|
|
191
|
-
background-color: var(--color-background-secondary);
|
|
192
|
-
border-radius: var(--border-radius-primary);
|
|
193
|
-
box-shadow: var(--box-shadow-secondary);
|
|
194
|
-
cursor: default;
|
|
195
|
-
transition: gap 0.2s ease, padding 0.2s ease;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.dashboard {
|
|
199
|
-
display: grid;
|
|
200
|
-
gap: 16px;
|
|
201
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.charts .headline {
|
|
205
|
-
display: flex;
|
|
206
|
-
justify-content: space-between;
|
|
207
|
-
gap: 12px;
|
|
208
|
-
flex-wrap: wrap;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.charts .headline .metrics {
|
|
212
|
-
display: flex;
|
|
213
|
-
flex-direction: row;
|
|
214
|
-
gap: 6px;
|
|
215
|
-
flex-wrap: wrap;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
.charts .headline .metrics .metric {
|
|
219
|
-
/* position:relative; */
|
|
220
|
-
/* max-width:max-content; */
|
|
221
|
-
padding: 13px 16px 10px;
|
|
222
|
-
background-color: var(--color-background-secondary);
|
|
223
|
-
border-radius: calc(var(--border-radius-primary) / 2);
|
|
224
|
-
overflow: hidden;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
.charts .headline .metrics .metric:before {
|
|
228
|
-
content: "";
|
|
229
|
-
position: absolute;
|
|
230
|
-
top: 0;
|
|
231
|
-
bottom: 0;
|
|
232
|
-
left: 0;
|
|
233
|
-
width: 0;
|
|
234
|
-
z-index: 1;
|
|
235
|
-
transition: width 0.15s ease, background-color 0.1s ease, border-radius 0.1s;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
.charts .headline .metrics .metric.clickable {
|
|
239
|
-
cursor: pointer;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
@media only screen and (min-width: 513px) {
|
|
243
|
-
.charts .headline .metrics .metric.clickable:not(.active):hover {
|
|
244
|
-
opacity: 0.8;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
.charts .headline .metrics .metric.active {
|
|
249
|
-
background-color: var(--color-background-elevation);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
.charts .headline .metrics .metric.active:before {
|
|
253
|
-
width: 2px;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
.charts .headline .metrics .metric.active.green:before {
|
|
257
|
-
background-color: var(--color-green);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.charts .headline .metrics .metric.active.yellow:before {
|
|
261
|
-
background-color: var(--color-yellow);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
.charts .headline .metrics .metric.active.red:before {
|
|
265
|
-
background-color: var(--color-red);
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
.charts .headline .metrics .metric.active h2 {
|
|
269
|
-
color: var(--color-primary);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
.charts .headline .metrics .metric > div {
|
|
273
|
-
display: flex;
|
|
274
|
-
align-items: center;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
.charts .headline .metrics .metric h2 {
|
|
278
|
-
margin: 0 6px 0 0;
|
|
279
|
-
font-size: 18px;
|
|
280
|
-
color: var(--color-secondary);
|
|
281
|
-
white-space: nowrap;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.charts .headline .metrics .metric .sum {
|
|
285
|
-
font-size: 28px;
|
|
286
|
-
font-weight: 500;
|
|
287
|
-
white-space: nowrap;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
.charts .headline .metrics .metric .tooltip .pop-over {
|
|
291
|
-
left: -128px;
|
|
292
|
-
width: 168px;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.charts .headline .metrics .metric .tooltip .pop-over:before {
|
|
296
|
-
left: 139px;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
.charts .headline .action {
|
|
300
|
-
position: absolute;
|
|
301
|
-
right: 24px;
|
|
302
|
-
bottom: 24px;
|
|
303
|
-
height: 20px;
|
|
304
|
-
width: 20px;
|
|
305
|
-
padding: 0;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
@media only screen and (min-width: 513px) {
|
|
309
|
-
.charts .headline .action:hover {
|
|
310
|
-
opacity: 0.8 !important;
|
|
311
|
-
background-color: transparent;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
.charts .headline .action i {
|
|
316
|
-
margin: 0;
|
|
317
|
-
font-size: 20px;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
@media only screen and (min-width: 769px) {
|
|
321
|
-
.charts.hidden {
|
|
322
|
-
gap: 0;
|
|
323
|
-
padding: 12px 8px 9px;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
@media only screen and (max-width: 768px) {
|
|
328
|
-
.charts {
|
|
329
|
-
flex: 1;
|
|
330
|
-
padding: 0;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
.charts .headline {
|
|
334
|
-
flex: 1;
|
|
335
|
-
padding: 12px 12px 9px;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
.charts .headline .metrics {
|
|
339
|
-
display: grid;
|
|
340
|
-
gap: 0;
|
|
341
|
-
grid-template-columns: auto;
|
|
342
|
-
flex: 1;
|
|
343
|
-
padding: 0;
|
|
344
|
-
overflow: hidden;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
.charts .headline .metrics .metric {
|
|
348
|
-
padding: 12px;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.charts .headline .metrics .metric:last-of-type {
|
|
352
|
-
grid-column: 1/3;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
.charts .headline .metrics .metric .sum {
|
|
356
|
-
white-space: nowrap;
|
|
357
|
-
overflow: hidden;
|
|
358
|
-
text-overflow: ellipsis;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
@media only screen and (max-width: 512px) {
|
|
363
|
-
.charts .headline {
|
|
364
|
-
padding: 8px;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
.charts .headline .action {
|
|
368
|
-
right: 20px;
|
|
369
|
-
bottom: 20px;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
.chart {
|
|
374
|
-
display: flex;
|
|
375
|
-
flex-direction: column;
|
|
376
|
-
margin-top: 12px;
|
|
377
|
-
margin-left: -8px;
|
|
378
|
-
background-color: transparent;
|
|
379
|
-
border-radius: var(--border-radius-primary);
|
|
380
|
-
cursor: default;
|
|
381
|
-
overflow-x: auto;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
.chart .chart-container {
|
|
385
|
-
position: relative;
|
|
386
|
-
height: 256px !important;
|
|
387
|
-
max-height: 60vh;
|
|
388
|
-
display: flex;
|
|
389
|
-
flex-direction: column;
|
|
390
|
-
padding: 0;
|
|
391
|
-
border-bottom-right-radius: calc(var(--border-radius-primary) / 2);
|
|
392
|
-
border-bottom-left-radius: calc(var(--border-radius-primary) / 2);
|
|
393
|
-
overflow: hidden;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
@media only screen and (max-width: 768px) {
|
|
397
|
-
.chart .chart-container {
|
|
398
|
-
width: 768px;
|
|
399
|
-
padding-bottom: 12px;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
.cv-page {
|
|
404
|
-
@apply text-lg;
|
|
405
|
-
& b {
|
|
406
|
-
font-weight: 600;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
& ul {
|
|
410
|
-
margin: 0.5rem;
|
|
411
|
-
padding-left: 2rem;
|
|
412
|
-
@media (--mobile) {
|
|
413
|
-
margin: 0.5rem;
|
|
414
|
-
padding-left: 1rem;
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
& li {
|
|
419
|
-
list-style-type: disc;
|
|
420
|
-
list-style-position: outside;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
& h3 {
|
|
424
|
-
font-weight: 700;
|
|
425
|
-
font-size: 1.2rem;
|
|
426
|
-
margin-top: 0.5rem;
|
|
427
|
-
margin-bottom: 0.5rem;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
& h4 {
|
|
431
|
-
font-weight: 500;
|
|
432
|
-
margin-top: 0.5rem;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
& h5 {
|
|
436
|
-
margin-top: 0.5rem;
|
|
437
|
-
}
|
|
438
|
-
}
|
svelte.config.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import adapterStatic from '@sveltejs/adapter-static';
|
|
2
2
|
|
|
3
3
|
/** @type {import('@sveltejs/kit').Config} */
|
|
4
4
|
const config = {
|
|
5
5
|
kit: {
|
|
6
|
-
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
|
7
|
-
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
|
8
|
-
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
|
9
|
-
adapter:
|
|
6
|
+
adapter: adapterStatic({
|
|
7
|
+
pages: 'build',
|
|
8
|
+
assets: 'build',
|
|
9
|
+
fallback: undefined,
|
|
10
|
+
precompress: false,
|
|
11
|
+
strict: false
|
|
10
|
-
|
|
12
|
+
})
|
|
13
|
+
}
|
|
11
14
|
};
|
|
12
15
|
|
|
13
16
|
export default config;
|
tailwind.config.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { type Config } from "tailwindcss";
|
|
2
|
-
import children from "tailwind-children";
|
|
3
|
-
|
|
4
|
-
export default {
|
|
5
|
-
plugins: [children],
|
|
6
|
-
content: ["{routes,islands,components}/**/*.{ts,tsx}"],
|
|
7
|
-
theme: {
|
|
8
|
-
fontFamily: {
|
|
9
|
-
sans: "system-ui",
|
|
10
|
-
serif: "system-ui",
|
|
11
|
-
mono: "monospace",
|
|
12
|
-
logo: "Kaiti SC",
|
|
13
|
-
},
|
|
14
|
-
data: {
|
|
15
|
-
current: "current",
|
|
16
|
-
},
|
|
17
|
-
extend: {
|
|
18
|
-
colors: {
|
|
19
|
-
yellow: "#f1fa8c",
|
|
20
|
-
black: "#1a1a1a",
|
|
21
|
-
"black-lighter": "#1f1f1f",
|
|
22
|
-
"black-light": "#313a3d",
|
|
23
|
-
"yellow-dark": "#858579",
|
|
24
|
-
"slider-bg": "#f0ede2",
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
} as Config;
|
uno.config.ts
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
import { defineConfig, presetIcons, presetUno } from
|
|
1
|
+
import { defineConfig, presetIcons, presetUno } from 'unocss';
|
|
2
|
-
import transformerVariantGroup from
|
|
2
|
+
import transformerVariantGroup from '@unocss/transformer-variant-group';
|
|
3
|
-
import transformerDirectives from '@unocss/transformer-directives'
|
|
3
|
+
import transformerDirectives from '@unocss/transformer-directives';
|
|
4
4
|
|
|
5
5
|
export default defineConfig({
|
|
6
6
|
presets: [
|
|
7
7
|
presetUno(),
|
|
8
|
-
presetIcons({
|
|
8
|
+
presetIcons({
|
|
9
|
-
|
|
9
|
+
autoInstall: true,
|
|
10
|
-
|
|
10
|
+
extraProperties: {
|
|
11
|
-
transformerVariantGroup(),
|
|
12
|
-
|
|
11
|
+
width: '2.25rem',
|
|
12
|
+
height: '2.25rem'
|
|
13
|
+
}
|
|
14
|
+
})
|
|
13
15
|
],
|
|
16
|
+
transformers: [transformerVariantGroup(), transformerDirectives()],
|
|
14
17
|
theme: {
|
|
15
18
|
fontFamily: {
|
|
16
|
-
sans:
|
|
19
|
+
sans: 'system-ui',
|
|
17
|
-
serif:
|
|
20
|
+
serif: 'system-ui',
|
|
18
|
-
mono:
|
|
21
|
+
mono: 'monospace',
|
|
19
|
-
logo:
|
|
22
|
+
logo: 'Kaiti SC'
|
|
20
|
-
}
|
|
23
|
+
}
|
|
21
|
-
}
|
|
24
|
+
}
|
|
22
25
|
});
|