website
git clone https://git.pyrossh.dev/website
木 Personal website of pyrossh. Built with astrojs, shiki, vite.
16367c8
— pyrossh
2025-04-26T23:03:46+05:30
add astro again :)
Generated files not shown: bun.lock, package-lock.json
- .gitignore +23 -9
- .vscode/extensions.json +2 -1
- .vscode/launch.json +11 -0
- .vscode/settings.json +0 -5
- README.md +68 -0
- astro.config.mjs +21 -0
- package.json +15 -41
- package2.json +46 -0
- public/blog-placeholder-1.jpg +0 -0
- public/blog-placeholder-2.jpg +0 -0
- public/blog-placeholder-3.jpg +0 -0
- public/blog-placeholder-4.jpg +0 -0
- public/blog-placeholder-5.jpg +0 -0
- public/blog-placeholder-about.jpg +0 -0
- public/favicon.svg +9 -0
- src/{lib/assets → assets}/icons/appstore.svg +0 -0
- src/{lib/assets → assets}/icons/playstore.svg +0 -0
- src/{lib/assets → assets}/images/app_icon.png +0 -0
- src/{lib/assets → assets}/images/app_image.png +0 -0
- src/{lib/assets → assets}/logos/code.png +0 -0
- src/{lib/assets → assets}/logos/helix.png +0 -0
- src/{lib/assets → assets}/logos/inkscape.png +0 -0
- src/{lib/assets → assets}/logos/iterm.png +0 -0
- src/{lib/assets → assets}/logos/nu.png +0 -0
- src/{lib/assets → assets}/logos/onlybible.png +0 -0
- src/{lib/assets → assets}/logos/pyrossh.png +0 -0
- src/{lib/assets → assets}/logos/rust.png +0 -0
- src/{lib/assets → assets}/logos/stats.png +0 -0
- src/{lib/assets → assets}/logos/zellij.png +0 -0
- src/components/BaseHead.astro +55 -0
- src/components/Footer.astro +41 -0
- src/components/FormattedDate.astro +11 -0
- src/components/Header.astro +77 -0
- src/components/HeaderLink.astro +14 -0
- src/components/Slide.astro +37 -0
- src/consts.ts +5 -0
- src/content.config.ts +18 -0
- src/{posts → content/blog}/eyecandy-golang-error-reporting.md +2 -2
- src/content/blog/first-post.md +16 -0
- src/{posts → content/blog}/gopibot-to-the-rescue.md +2 -2
- src/content/blog/markdown-style-guide.md +214 -0
- src/{posts → content/blog}/react-powertools-swr.md +2 -2
- src/content/blog/second-post.md +16 -0
- src/content/blog/third-post.md +16 -0
- src/content/blog/using-mdx.mdx +31 -0
- src/layouts/Base.astro +73 -0
- src/layouts/Post.astro +73 -0
- src/lib/components/Copyright.svelte +0 -9
- src/lib/components/Footer.svelte +0 -25
- src/lib/components/Header.svelte +0 -60
- src/lib/components/Intro.svelte +0 -11
- src/lib/components/Slide.svelte +0 -47
- src/lib/components/SocialLinks.svelte +0 -25
- src/lib/dateUtils.js +0 -5
- src/pages/cv/index.astro +240 -0
- src/pages/index.astro +263 -0
- src/pages/posts/[...slug].astro +75 -0
- src/pages/posts/index.astro +45 -0
- src/pages/rss.xml.js +16 -0
- src/routes/cv/+page.svelte +0 -229
- src/styles/global.css +150 -0
- {src → src2}/app.css +0 -0
- {src → src2}/app.d.ts +0 -0
- {src → src2}/app.html +0 -0
- {src → src2}/index.test.js +0 -0
- {src → src2}/routes/+error.svelte +0 -0
- {src → src2}/routes/+layout.js +0 -0
- {src → src2}/routes/+layout.svelte +2 -22
- {src → src2}/routes/+page.svelte +0 -29
- src2/routes/cv/+page.svelte +4 -0
- {src → src2}/routes/only-bible-app/+layout.svelte +0 -0
- {src → src2}/routes/only-bible-app/+page.svelte +0 -0
- {src → src2}/routes/only-bible-app/privacy-policy/+page.svelte +0 -0
- {src → src2}/routes/only-bible-app/terms-and-conditions/+page.svelte +0 -0
- {src → src2}/routes/posts/+page.js +0 -0
- {src → src2}/routes/posts/+page.svelte +0 -0
- {src → src2}/routes/posts/[slug]/+page.js +0 -0
- {src → src2}/routes/posts/[slug]/+page.svelte +0 -0
- {src → src2}/routes/sitemap.xml/+server.js +0 -0
- {src → src2}/vite-env.d.ts +0 -0
- tsconfig.json +12 -0
.gitignore
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
|
+
# build output
|
|
2
|
+
dist/
|
|
3
|
+
# generated types
|
|
1
|
-
.
|
|
4
|
+
.astro/
|
|
5
|
+
|
|
6
|
+
# dependencies
|
|
2
|
-
node_modules
|
|
7
|
+
node_modules/
|
|
8
|
+
|
|
9
|
+
# logs
|
|
3
|
-
|
|
10
|
+
npm-debug.log*
|
|
11
|
+
yarn-debug.log*
|
|
12
|
+
yarn-error.log*
|
|
13
|
+
pnpm-debug.log*
|
|
14
|
+
|
|
15
|
+
|
|
4
|
-
|
|
16
|
+
# environment variables
|
|
5
|
-
/package
|
|
6
17
|
.env
|
|
7
|
-
.env.*
|
|
8
|
-
|
|
18
|
+
.env.production
|
|
19
|
+
|
|
20
|
+
# macOS-specific files
|
|
21
|
+
.DS_Store
|
|
22
|
+
|
|
9
|
-
|
|
23
|
+
# jetbrains setting folder
|
|
10
|
-
|
|
24
|
+
.idea/
|
.vscode/extensions.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
2
|
+
"recommendations": ["astro-build.astro-vscode", "unifiedjs.vscode-mdx"],
|
|
3
|
+
"unwantedRecommendations": []
|
|
3
4
|
}
|
.vscode/launch.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"command": "./node_modules/.bin/astro dev",
|
|
6
|
+
"name": "Development server",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"type": "node-terminal"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
.vscode/settings.json
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"[html]": {
|
|
3
|
-
"editor.defaultFormatter": "vscode.html-language-features"
|
|
4
|
-
}
|
|
5
|
-
}
|
README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Astro Starter Kit: Blog
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
bun create astro@latest -- --template blog
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/blog)
|
|
8
|
+
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/blog)
|
|
9
|
+
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/blog/devcontainer.json)
|
|
10
|
+
|
|
11
|
+
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
Features:
|
|
16
|
+
|
|
17
|
+
- ✅ Minimal styling (make it your own!)
|
|
18
|
+
- ✅ 100/100 Lighthouse performance
|
|
19
|
+
- ✅ SEO-friendly with canonical URLs and OpenGraph data
|
|
20
|
+
- ✅ Sitemap support
|
|
21
|
+
- ✅ RSS Feed support
|
|
22
|
+
- ✅ Markdown & MDX support
|
|
23
|
+
|
|
24
|
+
## 🚀 Project Structure
|
|
25
|
+
|
|
26
|
+
Inside of your Astro project, you'll see the following folders and files:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
├── public/
|
|
30
|
+
├── src/
|
|
31
|
+
│ ├── components/
|
|
32
|
+
│ ├── content/
|
|
33
|
+
│ ├── layouts/
|
|
34
|
+
│ └── pages/
|
|
35
|
+
├── astro.config.mjs
|
|
36
|
+
├── README.md
|
|
37
|
+
├── package.json
|
|
38
|
+
└── tsconfig.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
|
42
|
+
|
|
43
|
+
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
|
44
|
+
|
|
45
|
+
The `src/content/` directory contains "collections" of related Markdown and MDX documents. Use `getCollection()` to retrieve posts from `src/content/blog/`, and type-check your frontmatter using an optional schema. See [Astro's Content Collections docs](https://docs.astro.build/en/guides/content-collections/) to learn more.
|
|
46
|
+
|
|
47
|
+
Any static assets, like images, can be placed in the `public/` directory.
|
|
48
|
+
|
|
49
|
+
## 🧞 Commands
|
|
50
|
+
|
|
51
|
+
All commands are run from the root of the project, from a terminal:
|
|
52
|
+
|
|
53
|
+
| Command | Action |
|
|
54
|
+
| :------------------------ | :----------------------------------------------- |
|
|
55
|
+
| `bun install` | Installs dependencies |
|
|
56
|
+
| `bun dev` | Starts local dev server at `localhost:4321` |
|
|
57
|
+
| `bun build` | Build your production site to `./dist/` |
|
|
58
|
+
| `bun preview` | Preview your build locally, before deploying |
|
|
59
|
+
| `bun astro ...` | Run CLI commands like `astro add`, `astro check` |
|
|
60
|
+
| `bun astro -- --help` | Get help using the Astro CLI |
|
|
61
|
+
|
|
62
|
+
## 👀 Want to learn more?
|
|
63
|
+
|
|
64
|
+
Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
|
65
|
+
|
|
66
|
+
## Credit
|
|
67
|
+
|
|
68
|
+
This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/).
|
astro.config.mjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { defineConfig, fontProviders } from 'astro/config';
|
|
3
|
+
import mdx from '@astrojs/mdx';
|
|
4
|
+
import sitemap from '@astrojs/sitemap';
|
|
5
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
6
|
+
|
|
7
|
+
// https://astro.build/config
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
site: 'https://pyrossh.dev',
|
|
10
|
+
integrations: [mdx(), sitemap()],
|
|
11
|
+
experimental: {
|
|
12
|
+
fonts: [{
|
|
13
|
+
provider: fontProviders.google(),
|
|
14
|
+
name: "Roboto",
|
|
15
|
+
cssVariable: "--font-roboto"
|
|
16
|
+
}]
|
|
17
|
+
},
|
|
18
|
+
vite: {
|
|
19
|
+
plugins: [tailwindcss()],
|
|
20
|
+
},
|
|
21
|
+
});
|
package.json
CHANGED
|
@@ -1,46 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "my-astro-project-using-bun",
|
|
3
|
-
"version": "0.0.1",
|
|
4
|
-
"private": true,
|
|
5
3
|
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
6
5
|
"scripts": {
|
|
7
|
-
"dev": "
|
|
6
|
+
"dev": "astro dev",
|
|
8
|
-
"build": "
|
|
7
|
+
"build": "astro build",
|
|
9
|
-
"preview": "
|
|
8
|
+
"preview": "astro preview",
|
|
10
|
-
"publish": "rm -rf build && npm run build && tar -C build -cvz . > site.tar.gz && hut pages publish -d pyrossh.dev site.tar.gz && rm site.tar.gz",
|
|
11
|
-
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
|
|
12
|
-
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
|
|
13
|
-
"test": "npm run test:integration && npm run test:unit",
|
|
14
|
-
"lint": "prettier --check . && eslint .",
|
|
15
|
-
"fmt": "prettier --write .",
|
|
16
|
-
"test:integration": "playwright test",
|
|
17
|
-
"
|
|
9
|
+
"astro": "astro"
|
|
18
10
|
},
|
|
19
|
-
"
|
|
11
|
+
"dependencies": {
|
|
20
|
-
"@iconify/svelte": "^4.0.2",
|
|
21
|
-
"@playwright/test": "^1.48.2",
|
|
22
|
-
"@poppanator/sveltekit-svg": "^5.0.0",
|
|
23
|
-
"@sveltejs/adapter-static": "^3.0.6",
|
|
24
|
-
"@sveltejs/enhanced-img": "^0.3.10",
|
|
25
|
-
"@
|
|
12
|
+
"@astrojs/mdx": "^4.2.5",
|
|
13
|
+
"@astrojs/rss": "^4.0.11",
|
|
14
|
+
"@astrojs/sitemap": "^3.3.1",
|
|
26
|
-
"@
|
|
15
|
+
"@effective/css-reset": "^3.2.0",
|
|
27
|
-
"@sveltejs/vite-plugin-svelte-inspector": "^3.0.1",
|
|
28
|
-
"@tailwindcss/vite": "^4.
|
|
16
|
+
"@tailwindcss/vite": "^4.1.4",
|
|
29
|
-
"@types/eslint": "8.56.0",
|
|
30
|
-
"autoprefixer": "^10.4.19",
|
|
31
|
-
"eslint": "^8.56.0",
|
|
32
|
-
"eslint-config-prettier": "^9.1.0",
|
|
33
|
-
"eslint-plugin-svelte": "^2.45.1",
|
|
34
|
-
"mdsvex": "^0.12.3",
|
|
35
|
-
"prettier": "^3.3.3",
|
|
36
|
-
"prettier-plugin-svelte": "^3.2.7",
|
|
37
|
-
"remark-github": "^12.0.0",
|
|
38
|
-
"shiki": "^1.22.1",
|
|
39
|
-
"super-sitemap": "^0.14.14",
|
|
40
|
-
"
|
|
17
|
+
"astro": "^5.7.5",
|
|
41
|
-
"svelte-check": "^4.0.5",
|
|
42
|
-
"tailwindcss": "^4.
|
|
18
|
+
"tailwindcss": "^4.1.4"
|
|
43
|
-
"vite": "^5.4.10",
|
|
44
|
-
"vitest": "^2.1.3"
|
|
45
19
|
}
|
|
46
|
-
}
|
|
20
|
+
}
|
package2.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "website",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite dev",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"publish": "rm -rf build && npm run build && tar -C build -cvz . > site.tar.gz && hut pages publish -d pyrossh.dev site.tar.gz && rm site.tar.gz",
|
|
11
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
|
|
12
|
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
|
|
13
|
+
"test": "npm run test:integration && npm run test:unit",
|
|
14
|
+
"lint": "prettier --check . && eslint .",
|
|
15
|
+
"fmt": "prettier --write .",
|
|
16
|
+
"test:integration": "playwright test",
|
|
17
|
+
"test:unit": "vitest"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@iconify/svelte": "^4.0.2",
|
|
21
|
+
"@playwright/test": "^1.48.2",
|
|
22
|
+
"@poppanator/sveltekit-svg": "^5.0.0",
|
|
23
|
+
"@sveltejs/adapter-static": "^3.0.6",
|
|
24
|
+
"@sveltejs/enhanced-img": "^0.3.10",
|
|
25
|
+
"@sveltejs/kit": "^2.7.3",
|
|
26
|
+
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
|
27
|
+
"@sveltejs/vite-plugin-svelte-inspector": "^3.0.1",
|
|
28
|
+
"@tailwindcss/vite": "^4.0.3",
|
|
29
|
+
"@types/eslint": "8.56.0",
|
|
30
|
+
"autoprefixer": "^10.4.19",
|
|
31
|
+
"eslint": "^8.56.0",
|
|
32
|
+
"eslint-config-prettier": "^9.1.0",
|
|
33
|
+
"eslint-plugin-svelte": "^2.45.1",
|
|
34
|
+
"mdsvex": "^0.12.3",
|
|
35
|
+
"prettier": "^3.3.3",
|
|
36
|
+
"prettier-plugin-svelte": "^3.2.7",
|
|
37
|
+
"remark-github": "^12.0.0",
|
|
38
|
+
"shiki": "^1.22.1",
|
|
39
|
+
"super-sitemap": "^0.14.14",
|
|
40
|
+
"svelte": "^5.1.3",
|
|
41
|
+
"svelte-check": "^4.0.5",
|
|
42
|
+
"tailwindcss": "^4.0.3",
|
|
43
|
+
"vite": "^5.4.10",
|
|
44
|
+
"vitest": "^2.1.3"
|
|
45
|
+
}
|
|
46
|
+
}
|
public/blog-placeholder-1.jpg
ADDED
|
Binary file
|
public/blog-placeholder-2.jpg
ADDED
|
Binary file
|
public/blog-placeholder-3.jpg
ADDED
|
Binary file
|
public/blog-placeholder-4.jpg
ADDED
|
Binary file
|
public/blog-placeholder-5.jpg
ADDED
|
Binary file
|
public/blog-placeholder-about.jpg
ADDED
|
Binary file
|
public/favicon.svg
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
|
2
|
+
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
|
3
|
+
<style>
|
|
4
|
+
path { fill: #000; }
|
|
5
|
+
@media (prefers-color-scheme: dark) {
|
|
6
|
+
path { fill: #FFF; }
|
|
7
|
+
}
|
|
8
|
+
</style>
|
|
9
|
+
</svg>
|
src/{lib/assets → assets}/icons/appstore.svg
RENAMED
|
File without changes
|
src/{lib/assets → assets}/icons/playstore.svg
RENAMED
|
File without changes
|
src/{lib/assets → assets}/images/app_icon.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/images/app_image.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/code.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/helix.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/inkscape.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/iterm.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/nu.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/onlybible.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/pyrossh.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/rust.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/stats.png
RENAMED
|
File without changes
|
src/{lib/assets → assets}/logos/zellij.png
RENAMED
|
File without changes
|
src/components/BaseHead.astro
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Import the global.css file here so that it is included on
|
|
3
|
+
// all pages through the use of the <BaseHead /> component.
|
|
4
|
+
import '../styles/global.css';
|
|
5
|
+
import { SITE_TITLE } from '../consts';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
image?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
|
14
|
+
|
|
15
|
+
const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props;
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
<!-- Global Metadata -->
|
|
19
|
+
<meta charset="utf-8" />
|
|
20
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
21
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
22
|
+
<link rel="sitemap" href="/sitemap-index.xml" />
|
|
23
|
+
<link
|
|
24
|
+
rel="alternate"
|
|
25
|
+
type="application/rss+xml"
|
|
26
|
+
title={SITE_TITLE}
|
|
27
|
+
href={new URL('rss.xml', Astro.site)}
|
|
28
|
+
/>
|
|
29
|
+
<meta name="generator" content={Astro.generator} />
|
|
30
|
+
|
|
31
|
+
<!-- Font preloads -->
|
|
32
|
+
<link rel="preload" href="/fonts/atkinson-regular.woff" as="font" type="font/woff" crossorigin />
|
|
33
|
+
<link rel="preload" href="/fonts/atkinson-bold.woff" as="font" type="font/woff" crossorigin />
|
|
34
|
+
|
|
35
|
+
<!-- Canonical URL -->
|
|
36
|
+
<link rel="canonical" href={canonicalURL} />
|
|
37
|
+
|
|
38
|
+
<!-- Primary Meta Tags -->
|
|
39
|
+
<title>{title}</title>
|
|
40
|
+
<meta name="title" content={title} />
|
|
41
|
+
<meta name="description" content={description} />
|
|
42
|
+
|
|
43
|
+
<!-- Open Graph / Facebook -->
|
|
44
|
+
<meta property="og:type" content="website" />
|
|
45
|
+
<meta property="og:url" content={Astro.url} />
|
|
46
|
+
<meta property="og:title" content={title} />
|
|
47
|
+
<meta property="og:description" content={description} />
|
|
48
|
+
<meta property="og:image" content={new URL(image, Astro.url)} />
|
|
49
|
+
|
|
50
|
+
<!-- Twitter -->
|
|
51
|
+
<meta property="twitter:card" content="summary_large_image" />
|
|
52
|
+
<meta property="twitter:url" content={Astro.url} />
|
|
53
|
+
<meta property="twitter:title" content={title} />
|
|
54
|
+
<meta property="twitter:description" content={description} />
|
|
55
|
+
<meta property="twitter:image" content={new URL(image, Astro.url)} />
|
src/components/Footer.astro
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
const today = new Date();
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<footer>
|
|
6
|
+
<div class="wrapper container">
|
|
7
|
+
<div class="flex-1"></div>
|
|
8
|
+
<div class="flex items-center justify-center mx-2">
|
|
9
|
+
<span class="text-base text-gray-200 hover:no-underline mr-2">
|
|
10
|
+
Copyright © {today.getFullYear()}
|
|
11
|
+
<a class="link" href="https://git.sr.ht/~pyrossh/"> pyrossh </a>
|
|
12
|
+
</span>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</footer>
|
|
16
|
+
<style>
|
|
17
|
+
footer {
|
|
18
|
+
background: var(--color-black);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.container {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: row;
|
|
24
|
+
flex: 1;
|
|
25
|
+
padding: 16px 0px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.link {
|
|
29
|
+
color: var(--color-white);
|
|
30
|
+
font-weight: 500;
|
|
31
|
+
text-underline-offset: 2px;
|
|
32
|
+
text-decoration-thickness: 2px;
|
|
33
|
+
text-decoration-line: underline;
|
|
34
|
+
text-decoration-color: white;
|
|
35
|
+
|
|
36
|
+
&:hover {
|
|
37
|
+
color: var(--color-gray-200);
|
|
38
|
+
text-decoration-color: var(--color-gray-200);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
</style>
|
src/components/FormattedDate.astro
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Props {
|
|
3
|
+
date: Date;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const { date } = Astro.props;
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<time datetime={date.toISOString()}>
|
|
10
|
+
{new Intl.DateTimeFormat('en-GB', { dateStyle: 'long' }).format(new Date(date))}
|
|
11
|
+
</time>
|
src/components/Header.astro
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
import HeaderLink from './HeaderLink.astro';
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<header>
|
|
6
|
+
<nav class="wrapper">
|
|
7
|
+
<HeaderLink class="logo" href="/"> 木 pyrossh </HeaderLink>
|
|
8
|
+
<div class="links">
|
|
9
|
+
<HeaderLink href="/cv">cv</HeaderLink>
|
|
10
|
+
<div>|</div>
|
|
11
|
+
<HeaderLink href="/posts">posts</HeaderLink>
|
|
12
|
+
<div>|</div>
|
|
13
|
+
<HeaderLink href="https://git.sr.ht/~pyrossh/">code</HeaderLink>
|
|
14
|
+
</div>
|
|
15
|
+
</nav>
|
|
16
|
+
</header>
|
|
17
|
+
<style>
|
|
18
|
+
header {
|
|
19
|
+
background-color: var(--color-black);
|
|
20
|
+
border-top: 5px solid #444;
|
|
21
|
+
border-bottom: 1px solid #444;
|
|
22
|
+
min-height: 56px;
|
|
23
|
+
position: relative;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
nav {
|
|
27
|
+
/* padding-left: 0px; */
|
|
28
|
+
/* padding-right: 0px; */
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.logo {
|
|
32
|
+
display: flex;
|
|
33
|
+
font-size: 22px;
|
|
34
|
+
line-height: 56px;
|
|
35
|
+
font-weight: 400;
|
|
36
|
+
margin-bottom: 0;
|
|
37
|
+
float: left;
|
|
38
|
+
color: var(--color-accent);
|
|
39
|
+
margin-right: 8px;
|
|
40
|
+
|
|
41
|
+
&.active,
|
|
42
|
+
&:hover {
|
|
43
|
+
color: var(--color-accent);
|
|
44
|
+
text-decoration: underline;
|
|
45
|
+
text-decoration-color: var(--color-accent);
|
|
46
|
+
text-underline-offset: 8px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.links {
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-direction: row;
|
|
53
|
+
float: right;
|
|
54
|
+
font-size: 22px;
|
|
55
|
+
line-height: 56px;
|
|
56
|
+
color: white;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.links a {
|
|
60
|
+
display: inline-block;
|
|
61
|
+
text-decoration: none;
|
|
62
|
+
font-size: 22px;
|
|
63
|
+
line-height: 56px;
|
|
64
|
+
color: white;
|
|
65
|
+
font-weight: 400;
|
|
66
|
+
padding-left: 12px;
|
|
67
|
+
padding-right: 12px;
|
|
68
|
+
|
|
69
|
+
&.active,
|
|
70
|
+
&:hover {
|
|
71
|
+
color: var(--color-gray-200);
|
|
72
|
+
text-decoration: underline;
|
|
73
|
+
text-decoration-color: var(--color-accent);
|
|
74
|
+
text-underline-offset: 8px;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
</style>
|
src/components/HeaderLink.astro
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types';
|
|
3
|
+
|
|
4
|
+
type Props = HTMLAttributes<'a'>;
|
|
5
|
+
|
|
6
|
+
const { href, class: className, ...props } = Astro.props;
|
|
7
|
+
const pathname = Astro.url.pathname.replace(import.meta.env.BASE_URL, '');
|
|
8
|
+
const subpath = pathname.match(/[^\/]+/g);
|
|
9
|
+
const isActive = href === pathname || href === '/' + (subpath?.[0] || '');
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<a href={href} class:list={[className, { active: isActive }]} {...props}>
|
|
13
|
+
<slot />
|
|
14
|
+
</a>
|
src/components/Slide.astro
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
const { title, link, isExternal = true } = Astro.props;
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<div class="card bg-[#f0ede2] rounded-xs">
|
|
6
|
+
<div class="card-body p-4">
|
|
7
|
+
<div class="card-title">
|
|
8
|
+
<slot name="icon" />
|
|
9
|
+
<a
|
|
10
|
+
class="link"
|
|
11
|
+
href={link}
|
|
12
|
+
target={isExternal ? '_blank' : '_self'}
|
|
13
|
+
rel={isExternal ? 'noopener noreferrer' : ''}
|
|
14
|
+
>
|
|
15
|
+
{title}
|
|
16
|
+
</a>
|
|
17
|
+
</div>
|
|
18
|
+
<slot />
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<style>
|
|
23
|
+
.card {
|
|
24
|
+
display: flex;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.card-title {
|
|
28
|
+
display: flex;
|
|
29
|
+
flex-direction: row;
|
|
30
|
+
align-items: center;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.link {
|
|
34
|
+
font-weight: 500;
|
|
35
|
+
text-decoration: underline;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
src/consts.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Place any global data in this file.
|
|
2
|
+
// You can import this data from anywhere in your site by using the `import` keyword.
|
|
3
|
+
|
|
4
|
+
export const SITE_TITLE = 'Astro Blog';
|
|
5
|
+
export const SITE_DESCRIPTION = 'Welcome to my website!';
|
src/content.config.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { glob } from 'astro/loaders';
|
|
2
|
+
import { defineCollection, z } from 'astro:content';
|
|
3
|
+
|
|
4
|
+
const blog = defineCollection({
|
|
5
|
+
// Load Markdown and MDX files in the `src/content/blog/` directory.
|
|
6
|
+
loader: glob({ base: './src/content/blog', pattern: '**/*.{md,mdx}' }),
|
|
7
|
+
// Type-check frontmatter using a schema
|
|
8
|
+
schema: z.object({
|
|
9
|
+
title: z.string(),
|
|
10
|
+
description: z.string(),
|
|
11
|
+
// Transform string to Date object
|
|
12
|
+
pubDate: z.coerce.date(),
|
|
13
|
+
updatedDate: z.coerce.date().optional(),
|
|
14
|
+
heroImage: z.string().optional(),
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const collections = { blog };
|
src/{posts → content/blog}/eyecandy-golang-error-reporting.md
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Eyecandy golang error reporting
|
|
3
3
|
description: Better error message logging in golang
|
|
4
|
-
|
|
4
|
+
heroImage: /images/terminal1.png
|
|
5
|
-
|
|
5
|
+
pubDate: 2016-09-17
|
|
6
6
|
tags:
|
|
7
7
|
- golang
|
|
8
8
|
- error
|
src/content/blog/first-post.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'First post'
|
|
3
|
+
description: 'Lorem ipsum dolor sit amet'
|
|
4
|
+
pubDate: 'Jul 08 2022'
|
|
5
|
+
heroImage: '/blog-placeholder-3.jpg'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
|
|
9
|
+
|
|
10
|
+
Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi.
|
|
11
|
+
|
|
12
|
+
Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim.
|
|
13
|
+
|
|
14
|
+
Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id cursus metus aliquam eleifend mi.
|
|
15
|
+
|
|
16
|
+
Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Egestas integer eget aliquet nibh praesent tristique magna.
|
src/{posts → content/blog}/gopibot-to-the-rescue.md
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Gopibot to the rescue
|
|
3
3
|
description: A slackbot for deploying your applications (chatops)
|
|
4
|
-
|
|
4
|
+
heroImage: /images/gopibot.png
|
|
5
|
-
|
|
5
|
+
pubDate: 2017-04-19
|
|
6
6
|
tags:
|
|
7
7
|
- nodejs
|
|
8
8
|
- slack
|
src/content/blog/markdown-style-guide.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Markdown Style Guide'
|
|
3
|
+
description: 'Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.'
|
|
4
|
+
pubDate: 'Jun 19 2024'
|
|
5
|
+
heroImage: '/blog-placeholder-1.jpg'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.
|
|
9
|
+
|
|
10
|
+
## Headings
|
|
11
|
+
|
|
12
|
+
The following HTML `<h1>`—`<h6>` elements represent six levels of section headings. `<h1>` is the highest section level while `<h6>` is the lowest.
|
|
13
|
+
|
|
14
|
+
# H1
|
|
15
|
+
|
|
16
|
+
## H2
|
|
17
|
+
|
|
18
|
+
### H3
|
|
19
|
+
|
|
20
|
+
#### H4
|
|
21
|
+
|
|
22
|
+
##### H5
|
|
23
|
+
|
|
24
|
+
###### H6
|
|
25
|
+
|
|
26
|
+
## Paragraph
|
|
27
|
+
|
|
28
|
+
Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.
|
|
29
|
+
|
|
30
|
+
Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.
|
|
31
|
+
|
|
32
|
+
## Images
|
|
33
|
+
|
|
34
|
+
### Syntax
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+

|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Output
|
|
41
|
+
|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
## Blockquotes
|
|
45
|
+
|
|
46
|
+
The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a `footer` or `cite` element, and optionally with in-line changes such as annotations and abbreviations.
|
|
47
|
+
|
|
48
|
+
### Blockquote without attribution
|
|
49
|
+
|
|
50
|
+
#### Syntax
|
|
51
|
+
|
|
52
|
+
```markdown
|
|
53
|
+
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
|
|
54
|
+
> **Note** that you can use _Markdown syntax_ within a blockquote.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### Output
|
|
58
|
+
|
|
59
|
+
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
|
|
60
|
+
> **Note** that you can use _Markdown syntax_ within a blockquote.
|
|
61
|
+
|
|
62
|
+
### Blockquote with attribution
|
|
63
|
+
|
|
64
|
+
#### Syntax
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
> Don't communicate by sharing memory, share memory by communicating.<br>
|
|
68
|
+
> — <cite>Rob Pike[^1]</cite>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### Output
|
|
72
|
+
|
|
73
|
+
> Don't communicate by sharing memory, share memory by communicating.<br>
|
|
74
|
+
> — <cite>Rob Pike[^1]</cite>
|
|
75
|
+
|
|
76
|
+
[^1]: The above quote is excerpted from Rob Pike's [talk](https://www.youtube.com/watch?v=PAAkCSZUG1c) during Gopherfest, November 18, 2015.
|
|
77
|
+
|
|
78
|
+
## Tables
|
|
79
|
+
|
|
80
|
+
### Syntax
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
| Italics | Bold | Code |
|
|
84
|
+
| --------- | -------- | ------ |
|
|
85
|
+
| _italics_ | **bold** | `code` |
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Output
|
|
89
|
+
|
|
90
|
+
| Italics | Bold | Code |
|
|
91
|
+
| --------- | -------- | ------ |
|
|
92
|
+
| _italics_ | **bold** | `code` |
|
|
93
|
+
|
|
94
|
+
## Code Blocks
|
|
95
|
+
|
|
96
|
+
### Syntax
|
|
97
|
+
|
|
98
|
+
we can use 3 backticks ``` in new line and write snippet and close with 3 backticks on new line and to highlight language specific syntax, write one word of language name after first 3 backticks, for eg. html, javascript, css, markdown, typescript, txt, bash
|
|
99
|
+
|
|
100
|
+
````markdown
|
|
101
|
+
```html
|
|
102
|
+
<!doctype html>
|
|
103
|
+
<html lang="en">
|
|
104
|
+
<head>
|
|
105
|
+
<meta charset="utf-8" />
|
|
106
|
+
<title>Example HTML5 Document</title>
|
|
107
|
+
</head>
|
|
108
|
+
<body>
|
|
109
|
+
<p>Test</p>
|
|
110
|
+
</body>
|
|
111
|
+
</html>
|
|
112
|
+
```
|
|
113
|
+
````
|
|
114
|
+
|
|
115
|
+
### Output
|
|
116
|
+
|
|
117
|
+
```html
|
|
118
|
+
<!doctype html>
|
|
119
|
+
<html lang="en">
|
|
120
|
+
<head>
|
|
121
|
+
<meta charset="utf-8" />
|
|
122
|
+
<title>Example HTML5 Document</title>
|
|
123
|
+
</head>
|
|
124
|
+
<body>
|
|
125
|
+
<p>Test</p>
|
|
126
|
+
</body>
|
|
127
|
+
</html>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## List Types
|
|
131
|
+
|
|
132
|
+
### Ordered List
|
|
133
|
+
|
|
134
|
+
#### Syntax
|
|
135
|
+
|
|
136
|
+
```markdown
|
|
137
|
+
1. First item
|
|
138
|
+
2. Second item
|
|
139
|
+
3. Third item
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### Output
|
|
143
|
+
|
|
144
|
+
1. First item
|
|
145
|
+
2. Second item
|
|
146
|
+
3. Third item
|
|
147
|
+
|
|
148
|
+
### Unordered List
|
|
149
|
+
|
|
150
|
+
#### Syntax
|
|
151
|
+
|
|
152
|
+
```markdown
|
|
153
|
+
- List item
|
|
154
|
+
- Another item
|
|
155
|
+
- And another item
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### Output
|
|
159
|
+
|
|
160
|
+
- List item
|
|
161
|
+
- Another item
|
|
162
|
+
- And another item
|
|
163
|
+
|
|
164
|
+
### Nested list
|
|
165
|
+
|
|
166
|
+
#### Syntax
|
|
167
|
+
|
|
168
|
+
```markdown
|
|
169
|
+
- Fruit
|
|
170
|
+
- Apple
|
|
171
|
+
- Orange
|
|
172
|
+
- Banana
|
|
173
|
+
- Dairy
|
|
174
|
+
- Milk
|
|
175
|
+
- Cheese
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### Output
|
|
179
|
+
|
|
180
|
+
- Fruit
|
|
181
|
+
- Apple
|
|
182
|
+
- Orange
|
|
183
|
+
- Banana
|
|
184
|
+
- Dairy
|
|
185
|
+
- Milk
|
|
186
|
+
- Cheese
|
|
187
|
+
|
|
188
|
+
## Other Elements — abbr, sub, sup, kbd, mark
|
|
189
|
+
|
|
190
|
+
### Syntax
|
|
191
|
+
|
|
192
|
+
```markdown
|
|
193
|
+
<abbr title="Graphics Interchange Format">GIF</abbr> is a bitmap image format.
|
|
194
|
+
|
|
195
|
+
H<sub>2</sub>O
|
|
196
|
+
|
|
197
|
+
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
|
198
|
+
|
|
199
|
+
Press <kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Delete</kbd> to end the session.
|
|
200
|
+
|
|
201
|
+
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Output
|
|
205
|
+
|
|
206
|
+
<abbr title="Graphics Interchange Format">GIF</abbr> is a bitmap image format.
|
|
207
|
+
|
|
208
|
+
H<sub>2</sub>O
|
|
209
|
+
|
|
210
|
+
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
|
211
|
+
|
|
212
|
+
Press <kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Delete</kbd> to end the session.
|
|
213
|
+
|
|
214
|
+
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
|
src/{posts → content/blog}/react-powertools-swr.md
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: 'React Powertools: SWR'
|
|
3
3
|
description: A react library that makes it easier to fetch data
|
|
4
|
-
|
|
4
|
+
heroImage: /images/gopibot.png
|
|
5
|
-
|
|
5
|
+
pubDate: 2024-08-16
|
|
6
6
|
tags:
|
|
7
7
|
- react
|
|
8
8
|
- frontend
|
src/content/blog/second-post.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Second post'
|
|
3
|
+
description: 'Lorem ipsum dolor sit amet'
|
|
4
|
+
pubDate: 'Jul 15 2022'
|
|
5
|
+
heroImage: '/blog-placeholder-4.jpg'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
|
|
9
|
+
|
|
10
|
+
Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi.
|
|
11
|
+
|
|
12
|
+
Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim.
|
|
13
|
+
|
|
14
|
+
Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id cursus metus aliquam eleifend mi.
|
|
15
|
+
|
|
16
|
+
Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Egestas integer eget aliquet nibh praesent tristique magna.
|
src/content/blog/third-post.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Third post'
|
|
3
|
+
description: 'Lorem ipsum dolor sit amet'
|
|
4
|
+
pubDate: 'Jul 22 2022'
|
|
5
|
+
heroImage: '/blog-placeholder-2.jpg'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
|
|
9
|
+
|
|
10
|
+
Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi.
|
|
11
|
+
|
|
12
|
+
Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim.
|
|
13
|
+
|
|
14
|
+
Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id cursus metus aliquam eleifend mi.
|
|
15
|
+
|
|
16
|
+
Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Egestas integer eget aliquet nibh praesent tristique magna.
|
src/content/blog/using-mdx.mdx
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Using MDX'
|
|
3
|
+
description: 'Lorem ipsum dolor sit amet'
|
|
4
|
+
pubDate: 'Jun 01 2024'
|
|
5
|
+
heroImage: '/blog-placeholder-5.jpg'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
This theme comes with the [@astrojs/mdx](https://docs.astro.build/en/guides/integrations-guide/mdx/) integration installed and configured in your `astro.config.mjs` config file. If you prefer not to use MDX, you can disable support by removing the integration from your config file.
|
|
9
|
+
|
|
10
|
+
## Why MDX?
|
|
11
|
+
|
|
12
|
+
MDX is a special flavor of Markdown that supports embedded JavaScript & JSX syntax. This unlocks the ability to [mix JavaScript and UI Components into your Markdown content](https://docs.astro.build/en/guides/markdown-content/#mdx-features) for things like interactive charts or alerts.
|
|
13
|
+
|
|
14
|
+
If you have existing content authored in MDX, this integration will hopefully make migrating to Astro a breeze.
|
|
15
|
+
|
|
16
|
+
## Example
|
|
17
|
+
|
|
18
|
+
Here is how you import and use a UI component inside of MDX.
|
|
19
|
+
When you open this page in the browser, you should see the clickable button below.
|
|
20
|
+
|
|
21
|
+
import HeaderLink from '../../components/HeaderLink.astro';
|
|
22
|
+
|
|
23
|
+
<HeaderLink href="#" onclick="alert('clicked!')">
|
|
24
|
+
Embedded component in MDX
|
|
25
|
+
</HeaderLink>
|
|
26
|
+
|
|
27
|
+
## More Links
|
|
28
|
+
|
|
29
|
+
- [MDX Syntax Documentation](https://mdxjs.com/docs/what-is-mdx)
|
|
30
|
+
- [Astro Usage Documentation](https://docs.astro.build/en/guides/markdown-content/#markdown-and-mdx-pages)
|
|
31
|
+
- **Note:** [Client Directives](https://docs.astro.build/en/reference/directives-reference/#client-directives) are still required to create interactive components. Otherwise, all components in your MDX will render as static HTML (no JavaScript) by default.
|
src/layouts/Base.astro
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Font } from 'astro:assets';
|
|
3
|
+
import BaseHead from '../components/BaseHead.astro';
|
|
4
|
+
import Header from '../components/Header.astro';
|
|
5
|
+
import Footer from '../components/Footer.astro';
|
|
6
|
+
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
|
|
7
|
+
// import '@effective/css-reset';
|
|
8
|
+
import './src/styles/global.css';
|
|
9
|
+
|
|
10
|
+
const { title, description } = Astro.props;
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<!doctype html>
|
|
14
|
+
<html lang="en">
|
|
15
|
+
<head>
|
|
16
|
+
<!-- <title slot="head"></title> -->
|
|
17
|
+
<!-- <meta name="author" content="pyrossh" />
|
|
18
|
+
<meta name="keywords" content="pyrossh.dev,pyrossh,svelte,website" />
|
|
19
|
+
<link rel="canonical" href={url} />
|
|
20
|
+
<meta property="og:site_name" content="pyrossh.dev" />
|
|
21
|
+
<meta property="og:type" content="website" />
|
|
22
|
+
<meta property="og:url" content={url} /> -->
|
|
23
|
+
<BaseHead title={title} description={description} />
|
|
24
|
+
<Font cssVariable="--font-roboto" preload />
|
|
25
|
+
</head>
|
|
26
|
+
<body>
|
|
27
|
+
<div class="flex flex-1 flex-col">
|
|
28
|
+
<Header />
|
|
29
|
+
<main class="wrapper">
|
|
30
|
+
<slot />
|
|
31
|
+
<!-- <div class="flex flex-1 flex-row">
|
|
32
|
+
<div class="flex flex-1 flex-row my-4">
|
|
33
|
+
<slot />
|
|
34
|
+
</div>
|
|
35
|
+
</div> -->
|
|
36
|
+
</main>
|
|
37
|
+
<Footer />
|
|
38
|
+
</div>
|
|
39
|
+
</body>
|
|
40
|
+
</html>
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
html {
|
|
44
|
+
background-color: white;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
body {
|
|
48
|
+
/* margin: 0;
|
|
49
|
+
padding: 0;
|
|
50
|
+
text-align: left;
|
|
51
|
+
background: linear-gradient(var(--gray-gradient)) no-repeat;
|
|
52
|
+
background-size: 100% 600px;
|
|
53
|
+
word-wrap: break-word;
|
|
54
|
+
overflow-wrap: break-word;
|
|
55
|
+
color: rgb(var(--gray-dark));
|
|
56
|
+
font-size: 20px;
|
|
57
|
+
line-height: 1.7; */
|
|
58
|
+
background-color: var(--color-white);
|
|
59
|
+
font-family: var(--font-roboto);
|
|
60
|
+
text-rendering: optimizeLegibility;
|
|
61
|
+
font-variant-ligatures: common-ligatures;
|
|
62
|
+
font-kerning: normal;
|
|
63
|
+
font-size: 14pt;
|
|
64
|
+
line-height: 1.6;
|
|
65
|
+
color: #222;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
main {
|
|
69
|
+
background-color: var(--color-white);
|
|
70
|
+
padding-top: 1em;
|
|
71
|
+
padding-bottom: 1em;
|
|
72
|
+
}
|
|
73
|
+
</style>
|
src/layouts/Post.astro
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { CollectionEntry } from 'astro:content';
|
|
3
|
+
import FormattedDate from '../components/FormattedDate.astro';
|
|
4
|
+
import Layout from './Base.astro';
|
|
5
|
+
|
|
6
|
+
type Props = CollectionEntry<'blog'>['data'];
|
|
7
|
+
|
|
8
|
+
const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<Layout>
|
|
12
|
+
<article>
|
|
13
|
+
<div class="hero-image">
|
|
14
|
+
{heroImage && <img width={1020} height={510} src={heroImage} alt="" />}
|
|
15
|
+
</div>
|
|
16
|
+
<div class="prose">
|
|
17
|
+
<div class="title">
|
|
18
|
+
<div class="date">
|
|
19
|
+
<FormattedDate date={pubDate} />
|
|
20
|
+
{
|
|
21
|
+
updatedDate && (
|
|
22
|
+
<div class="last-updated-on">
|
|
23
|
+
Last updated on <FormattedDate date={updatedDate} />
|
|
24
|
+
</div>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
</div>
|
|
28
|
+
<h1>{title}</h1>
|
|
29
|
+
<hr />
|
|
30
|
+
</div>
|
|
31
|
+
<slot />
|
|
32
|
+
</div>
|
|
33
|
+
</article>
|
|
34
|
+
</Layout>
|
|
35
|
+
<style>
|
|
36
|
+
main {
|
|
37
|
+
width: calc(100% - 2em);
|
|
38
|
+
max-width: 100%;
|
|
39
|
+
margin: 0;
|
|
40
|
+
}
|
|
41
|
+
.hero-image {
|
|
42
|
+
width: 100%;
|
|
43
|
+
}
|
|
44
|
+
.hero-image img {
|
|
45
|
+
display: block;
|
|
46
|
+
margin: 0 auto;
|
|
47
|
+
border-radius: 12px;
|
|
48
|
+
box-shadow: var(--box-shadow);
|
|
49
|
+
}
|
|
50
|
+
.prose {
|
|
51
|
+
width: 720px;
|
|
52
|
+
max-width: calc(100% - 2em);
|
|
53
|
+
margin: auto;
|
|
54
|
+
padding: 1em;
|
|
55
|
+
color: rgb(var(--gray-dark));
|
|
56
|
+
}
|
|
57
|
+
.title {
|
|
58
|
+
margin-bottom: 1em;
|
|
59
|
+
padding: 1em 0;
|
|
60
|
+
text-align: center;
|
|
61
|
+
line-height: 1;
|
|
62
|
+
}
|
|
63
|
+
.title h1 {
|
|
64
|
+
margin: 0 0 0.5em 0;
|
|
65
|
+
}
|
|
66
|
+
.date {
|
|
67
|
+
margin-bottom: 0.5em;
|
|
68
|
+
color: rgb(var(--gray));
|
|
69
|
+
}
|
|
70
|
+
.last-updated-on {
|
|
71
|
+
font-style: italic;
|
|
72
|
+
}
|
|
73
|
+
</style>
|
src/lib/components/Copyright.svelte
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
<span class="text-base text-gray-200 hover:no-underline mr-2"
|
|
2
|
-
>Copyright © {new Date().getFullYear()}
|
|
3
|
-
<a
|
|
4
|
-
class="decoration-2 underline underline-offset-2 font-medium hover:text-gray-400 hover:decoration-gray-400"
|
|
5
|
-
href="https://git.sr.ht/~pyrossh/"
|
|
6
|
-
>
|
|
7
|
-
pyrossh
|
|
8
|
-
</a>
|
|
9
|
-
</span>
|
src/lib/components/Footer.svelte
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import Copyright from './Copyright.svelte';
|
|
3
|
-
import SocialLinks from './SocialLinks.svelte';
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<footer class="bg-black">
|
|
7
|
-
<div class="wrapper flex flex-row flex-1 py-4 px-3 max-w-5xl">
|
|
8
|
-
<div class="flex-1">
|
|
9
|
-
<SocialLinks />
|
|
10
|
-
</div>
|
|
11
|
-
<div class="flex items-center justify-center mx-2">
|
|
12
|
-
<Copyright />
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
</footer>
|
|
16
|
-
|
|
17
|
-
<style>
|
|
18
|
-
.wrapper {
|
|
19
|
-
max-width: calc(95ex - (1em * 2));
|
|
20
|
-
margin-right: auto;
|
|
21
|
-
margin-left: auto;
|
|
22
|
-
padding-left: 1em;
|
|
23
|
-
padding-right: 1em;
|
|
24
|
-
}
|
|
25
|
-
</style>
|
src/lib/components/Header.svelte
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { page } from '$app/stores';
|
|
3
|
-
let isActive = $derived((href) => $page.url.pathname.includes(href));
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<header>
|
|
7
|
-
<nav class="wrapper">
|
|
8
|
-
<a class="flex text-[#f1fa8c] mr-4 logo" href="/">
|
|
9
|
-
<span class="mr-1">木</span> pyrossh
|
|
10
|
-
</a>
|
|
11
|
-
<div class="links">
|
|
12
|
-
<a href="/cv" class:underline={isActive('/cv')} rel="prefetch"> cv </a>
|
|
13
|
-
<div>|</div>
|
|
14
|
-
<a href="/posts" class:underline={isActive('/posts')} rel="prefetch"> posts </a>
|
|
15
|
-
<div class="hidden sm:block">|</div>
|
|
16
|
-
<a class="hidden sm:block" href="https://git.sr.ht/~pyrossh/"> code </a>
|
|
17
|
-
</div>
|
|
18
|
-
</nav>
|
|
19
|
-
</header>
|
|
20
|
-
|
|
21
|
-
<style>
|
|
22
|
-
header {
|
|
23
|
-
background-color: black;
|
|
24
|
-
border-top: 5px solid #444;
|
|
25
|
-
border-bottom: 1px solid #444;
|
|
26
|
-
min-height: 56px;
|
|
27
|
-
position: relative;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.wrapper {
|
|
31
|
-
max-width: calc(95ex - (1em * 2));
|
|
32
|
-
margin-right: auto;
|
|
33
|
-
margin-left: auto;
|
|
34
|
-
padding-left: 1em;
|
|
35
|
-
padding-right: 1em;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.logo {
|
|
39
|
-
font-size: 22px;
|
|
40
|
-
line-height: 56px;
|
|
41
|
-
font-weight: 500;
|
|
42
|
-
margin-bottom: 0;
|
|
43
|
-
float: left;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.links {
|
|
47
|
-
display: flex;
|
|
48
|
-
flex-direction: row;
|
|
49
|
-
float: right;
|
|
50
|
-
font-size: 22px;
|
|
51
|
-
line-height: 56px;
|
|
52
|
-
color: white;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.links a {
|
|
56
|
-
font-weight: 500;
|
|
57
|
-
padding-left: 12px;
|
|
58
|
-
padding-right: 12px;
|
|
59
|
-
}
|
|
60
|
-
</style>
|
src/lib/components/Intro.svelte
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<h1 class="text-xl text-center sm:text-left lg:leading-tight mt-3">
|
|
2
|
-
The only bible app you will ever need
|
|
3
|
-
</h1>
|
|
4
|
-
<div class="text-center sm:text-left flex flex-col text-lg sm:mt-5">
|
|
5
|
-
<p>No ads</p>
|
|
6
|
-
<p>No in-app purchases</p>
|
|
7
|
-
<p>No distractions</p>
|
|
8
|
-
<p>Offline First</p>
|
|
9
|
-
<p>Optimized reading</p>
|
|
10
|
-
<p>Online Audio Playback</p>
|
|
11
|
-
</div>
|
src/lib/components/Slide.svelte
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
/**
|
|
3
|
-
* @typedef {Object} Props
|
|
4
|
-
* @property {any} title - let { title, link, children } = $props();
|
|
5
|
-
* @property {any} link - let { title, link, children } = $props();
|
|
6
|
-
* @property {boolean} [isExternal] - let { title, link, children } = $props();
|
|
7
|
-
* @property {import('svelte').Snippet} [icon]
|
|
8
|
-
* @property {import('svelte').Snippet} [children]
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/** @type {Props} */
|
|
12
|
-
let { title, link, isExternal = true, icon, children } = $props();
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
<div class="card bg-[#f0ede2] rounded-xs">
|
|
16
|
-
<div class="card-body p-4">
|
|
17
|
-
<div class="card-title">
|
|
18
|
-
{@render icon?.()}
|
|
19
|
-
<a
|
|
20
|
-
class="link"
|
|
21
|
-
href={link}
|
|
22
|
-
target={isExternal ? '_blank' : ''}
|
|
23
|
-
rel={isExternal ? 'noopener noreferrer' : ''}
|
|
24
|
-
>
|
|
25
|
-
{title}
|
|
26
|
-
</a>
|
|
27
|
-
</div>
|
|
28
|
-
{@render children?.()}
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
|
|
32
|
-
<style>
|
|
33
|
-
.card {
|
|
34
|
-
display: flex;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.card-title {
|
|
38
|
-
display: flex;
|
|
39
|
-
flex-direction: row;
|
|
40
|
-
align-items: center;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.link {
|
|
44
|
-
font-weight: 500;
|
|
45
|
-
text-decoration: underline;
|
|
46
|
-
}
|
|
47
|
-
</style>
|
src/lib/components/SocialLinks.svelte
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import Icon from '@iconify/svelte';
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<div class="flex hover:no-underline text-white *:mx-2">
|
|
6
|
-
<a
|
|
7
|
-
href="https://linkedin.com/in/pyrossh"
|
|
8
|
-
title="My LinkedIn profile"
|
|
9
|
-
target="_blank"
|
|
10
|
-
rel="noopener noreferrer"
|
|
11
|
-
>
|
|
12
|
-
<Icon class="" icon="mdi:linkedin" width="36" />
|
|
13
|
-
</a>
|
|
14
|
-
<a
|
|
15
|
-
href="https://github.com/pyrossh"
|
|
16
|
-
title="My GitHub profile"
|
|
17
|
-
target="_blank"
|
|
18
|
-
rel="noopener noreferrer"
|
|
19
|
-
>
|
|
20
|
-
<Icon icon="mdi:github" width="36" />
|
|
21
|
-
</a>
|
|
22
|
-
<a href="mailto:[email protected]" title="My email" target="_blank" rel="noopener noreferrer">
|
|
23
|
-
<Icon icon="mdi:email-outline" width="36" />
|
|
24
|
-
</a>
|
|
25
|
-
</div>
|
src/lib/dateUtils.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export const formatDate = (d) =>
|
|
2
|
-
new Intl.DateTimeFormat('en-GB').format(new Date(d)).replaceAll('/', '-');
|
|
3
|
-
|
|
4
|
-
export const formatDateLong = (d) =>
|
|
5
|
-
new Intl.DateTimeFormat('en-GB', { dateStyle: 'long' }).format(new Date(d));
|
src/pages/cv/index.astro
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Layout from '@/layouts/Base.astro';
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<Layout
|
|
6
|
+
title="CV"
|
|
7
|
+
description="Lorem ipsum dolor sit amet"
|
|
8
|
+
pubDate={new Date('August 08 2021')}
|
|
9
|
+
heroImage="/blog-placeholder-about.jpg"
|
|
10
|
+
>
|
|
11
|
+
<div>
|
|
12
|
+
<section>
|
|
13
|
+
<h3>Equal Experts</h3>
|
|
14
|
+
<h4>Software Developer, Oct 2018 - present</h4>
|
|
15
|
+
<h5>
|
|
16
|
+
Making Software. Better. Equal Experts is a network of talented, experienced software
|
|
17
|
+
consultants, specialising in agile delivery.
|
|
18
|
+
</h5>
|
|
19
|
+
<div>
|
|
20
|
+
These are the client projects I worked on,
|
|
21
|
+
<ul>
|
|
22
|
+
<li>
|
|
23
|
+
<h6>John Lewis <span>(Mar '21 - Aug '24)</span></h6>
|
|
24
|
+
<ul class="*:list-disc">
|
|
25
|
+
<li>
|
|
26
|
+
Built a quiz memory game with leaderboard scoring to improve engagement during
|
|
27
|
+
Christmas
|
|
28
|
+
</li>
|
|
29
|
+
<li>
|
|
30
|
+
Implemented new features for customer self-serve actions in returns, cancellations,
|
|
31
|
+
tracking
|
|
32
|
+
</li>
|
|
33
|
+
<li>
|
|
34
|
+
Refactored the old self-serve React app to use Nextjs and removed a large dependency
|
|
35
|
+
on redux
|
|
36
|
+
</li>
|
|
37
|
+
<li>
|
|
38
|
+
Ran many experiments in the customer services and order pages to improve our metrics
|
|
39
|
+
and reduce contacts
|
|
40
|
+
</li>
|
|
41
|
+
<li>
|
|
42
|
+
Built the new Product Description Page (PDP) for Simple Carpets using a micro
|
|
43
|
+
frontend architecture
|
|
44
|
+
</li>
|
|
45
|
+
<li>
|
|
46
|
+
<b>Technologies & Tools</b>: Nodejs, Nextjs, Reactjs, Kotlin, K8s, Grafana, Kibana,
|
|
47
|
+
Firestore, Google Sheets API, Monetate, Adobe Analytics, Scene7, Adobe AEM
|
|
48
|
+
</li>
|
|
49
|
+
</ul>
|
|
50
|
+
</li>
|
|
51
|
+
<li>
|
|
52
|
+
<h6>iOWNA <span>(Mar '20 - Mar '21)</span></h6>
|
|
53
|
+
<ul class="*:list-disc">
|
|
54
|
+
<li>Built a Content Editor for curators to create content on our platform</li>
|
|
55
|
+
<li>
|
|
56
|
+
Built the iOWNA crossplatform app in react-native that works in android, ios, and
|
|
57
|
+
web using one codebase.
|
|
58
|
+
</li>
|
|
59
|
+
<li>Implemented Admin specific functionalities in the web app</li>
|
|
60
|
+
<li>Implemented an in-app OTA update method using expo and semantic versioning.</li>
|
|
61
|
+
<li>Built the iOWNA marketing website</li>
|
|
62
|
+
<li>
|
|
63
|
+
Built the Health Questionnaire clinician/patient feedback form feature with push
|
|
64
|
+
notifications
|
|
65
|
+
</li>
|
|
66
|
+
<li>
|
|
67
|
+
<b>Technologies & Tools</b>: Go, Javascript, React Native, Expo, GraphQL,
|
|
68
|
+
Serverless, AppSync, Cognito, Dynamodb, API Gateway, Lambda, Cloudformation
|
|
69
|
+
</li>
|
|
70
|
+
</ul>
|
|
71
|
+
</li>
|
|
72
|
+
<li>
|
|
73
|
+
<h6>Zeta <span>(Nov '19 - Feb '20)</span></h6>
|
|
74
|
+
<ul class="*:list-disc">
|
|
75
|
+
<li>
|
|
76
|
+
Added multiple download formats (pdf,html,xlsx) for reports in the Reporting Center
|
|
77
|
+
</li>
|
|
78
|
+
<li>
|
|
79
|
+
Created a Groovy Script to automate creating ACL in sandbox authorization framework
|
|
80
|
+
</li>
|
|
81
|
+
<li>Integrated Camunda Workflow Engine into Zeta services in Operations Center</li>
|
|
82
|
+
<li>
|
|
83
|
+
Built a few workflows on Camunda and integrated it with some internal services
|
|
84
|
+
</li>
|
|
85
|
+
<li>
|
|
86
|
+
Built a custom k8s CRD using the operator framework to automate creating ACL in
|
|
87
|
+
sandbox using custom resources
|
|
88
|
+
</li>
|
|
89
|
+
<li>
|
|
90
|
+
<b>Technologies & Tools</b>: Go, Java, Springboot, Camunda, Postgres, Docker, K8s
|
|
91
|
+
</li>
|
|
92
|
+
</ul>
|
|
93
|
+
</li>
|
|
94
|
+
<li>
|
|
95
|
+
<h6>Lifebox <span>(Oct '18 - Oct '19)</span></h6>
|
|
96
|
+
<ul class="*:list-disc">
|
|
97
|
+
<li>Added search functionality to the hospital procedure codes</li>
|
|
98
|
+
<li>
|
|
99
|
+
Converted the Health Questionnaire from json to native go code making it easier to
|
|
100
|
+
make changes to it
|
|
101
|
+
</li>
|
|
102
|
+
<li>
|
|
103
|
+
Integrated with SAP using HL7 message format to create patients, episodes,
|
|
104
|
+
schedule/cancel procedures
|
|
105
|
+
</li>
|
|
106
|
+
<li>
|
|
107
|
+
Built the Patient Document repository for uploading, downloading patient files
|
|
108
|
+
</li>
|
|
109
|
+
<li>Built the patients online reports view using the data from SAP</li>
|
|
110
|
+
<li>
|
|
111
|
+
<b>Technologies & Tools</b>: Go, Javascript, Reactjs, K6, Serverless, Grafana,
|
|
112
|
+
Cognito, Dynamodb, API Gateway , Lambda, GraphQL, Cloudformation, SQLite3
|
|
113
|
+
</li>
|
|
114
|
+
</ul>
|
|
115
|
+
</li>
|
|
116
|
+
</ul>
|
|
117
|
+
</div>
|
|
118
|
+
</section>
|
|
119
|
+
<section>
|
|
120
|
+
<h3>Numberz</h3>
|
|
121
|
+
<h4>Full Stack Developer, Sept 2016 - Oct 2018</h4>
|
|
122
|
+
<h5>
|
|
123
|
+
Numberz integrates banking with your day-2-day business work-flows freeing up a lot of
|
|
124
|
+
effort, time and heart-burn, to help your business grow.
|
|
125
|
+
</h5>
|
|
126
|
+
<ul class="*:list-disc">
|
|
127
|
+
<li>Implemented new features and fixed bugs on the numberz android app</li>
|
|
128
|
+
<li>Integrated numberz with Tally ERP (export and import of sales, purchases)</li>
|
|
129
|
+
<li>
|
|
130
|
+
Implemented CI and Devops within out system to ease our deployment process using docker
|
|
131
|
+
and docker-compose
|
|
132
|
+
</li>
|
|
133
|
+
<li>
|
|
134
|
+
Created a slack bot called deploybot which was used to deploy our microservices to our
|
|
135
|
+
servers
|
|
136
|
+
</li>
|
|
137
|
+
<li>Started tech talks on Thursdays to discuss cutting edge technologies</li>
|
|
138
|
+
<li>Architected and built the Notification Service using rabbitmq and nodejs</li>
|
|
139
|
+
<li>Built the Multi-User and Multi-Company Features</li>
|
|
140
|
+
<li>
|
|
141
|
+
Implemented and lead a team on integration with the GSTN System so that customers could
|
|
142
|
+
file their GST Taxes within our product
|
|
143
|
+
</li>
|
|
144
|
+
<li>Architected and built the numberz Identity Management Service(IMS)</li>
|
|
145
|
+
<li>Architected our new product called the Numberz Accounts Receivable (AR)</li>
|
|
146
|
+
<li>Laid down the architecture for the frontend and backend</li>
|
|
147
|
+
<li>
|
|
148
|
+
Built these core features for our new AR Product - Auto Reminders, Manual Reminders, User
|
|
149
|
+
Management, Cash Discounting, CFO Dashboard Metrics
|
|
150
|
+
</li>
|
|
151
|
+
<li>
|
|
152
|
+
<b>Technologies & Tools</b>: Nodejs, Mongodb, Postgres, GraphQL, Ansible, K8s, Typescript,
|
|
153
|
+
Reactjs
|
|
154
|
+
</li>
|
|
155
|
+
</ul>
|
|
156
|
+
</section>
|
|
157
|
+
<section>
|
|
158
|
+
<h3>Playlyfe</h3>
|
|
159
|
+
<h4>Full Stack Developer, Apr 2014 - Sept 2016</h4>
|
|
160
|
+
<h5>
|
|
161
|
+
Playlyfe is an online Gamification Platform which empowers anyone to design and implement a
|
|
162
|
+
gamified system.
|
|
163
|
+
</h5>
|
|
164
|
+
<ul class="*:list-disc">
|
|
165
|
+
<li>Built the Playlyfe Hybrid Mobile app using Phonegap for Android and iOS</li>
|
|
166
|
+
<li>Built the leaderboard system using Mongodb, Redis and Couchbase as the datastore</li>
|
|
167
|
+
<li>Migration of data from v1 to v2 of the API</li>
|
|
168
|
+
<li>Built SDKs for the Playlyfe v2 API in C#, Java, Python, Ruby, PHP, Nodejs, Gos</li>
|
|
169
|
+
<li>Maintained the job server and wrote most of the background jobs</li>
|
|
170
|
+
<li>
|
|
171
|
+
Added documentation to most of the REST API and created the Developer Console which was
|
|
172
|
+
Like Swagger UI
|
|
173
|
+
</li>
|
|
174
|
+
<li>Integrated our REST API in Leanosphere's LMS</li>
|
|
175
|
+
<li>Integrated the REST API in Knolskape's product Aktivlearn LMS</li>
|
|
176
|
+
<li>Integrated the REST API in Linkstreet's LMS</li>
|
|
177
|
+
<li>
|
|
178
|
+
Integrated the REST API in Moodle LMS by creating an admin plugin to add Gamification
|
|
179
|
+
features
|
|
180
|
+
</li>
|
|
181
|
+
<li>Rebuilt the core platform in golang for performance and developement speed</li>
|
|
182
|
+
<li>Built the GraphQL API for our cutting edge product Catalyst</li>
|
|
183
|
+
<li>
|
|
184
|
+
Convinced the boss to create our own scripting language plscript for our rule engine.
|
|
185
|
+
</li>
|
|
186
|
+
<li>Build a REST API for our product catalyst for a POC with Vodafone</li>
|
|
187
|
+
<li>
|
|
188
|
+
Built the Quiz, Review, Match, Tournament features in Catalyst for a major project with HP
|
|
189
|
+
</li>
|
|
190
|
+
<li>Added gamification features to Saudi Matches a popular game tracking app</li>
|
|
191
|
+
<li>
|
|
192
|
+
<b>Technologies & Tools</b>: Nodejs, Coffeescript, Angularjs, Mongodb, Couchbase, Redis,
|
|
193
|
+
Seaweedfs, Postgres, Golang, GraphQL, Relay, React
|
|
194
|
+
</li>
|
|
195
|
+
</ul>
|
|
196
|
+
</section>
|
|
197
|
+
</div>
|
|
198
|
+
</Layout>
|
|
199
|
+
<style>
|
|
200
|
+
b {
|
|
201
|
+
font-weight: 600;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
ul {
|
|
205
|
+
margin: 0.5rem;
|
|
206
|
+
padding-left: 1rem;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
li {
|
|
210
|
+
list-style-type: disc;
|
|
211
|
+
list-style-position: outside;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
h3 {
|
|
215
|
+
font-weight: 700;
|
|
216
|
+
font-size: 1.4rem;
|
|
217
|
+
margin-top: 0.5rem;
|
|
218
|
+
margin-bottom: 0.5rem;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
h4 {
|
|
222
|
+
font-weight: 600;
|
|
223
|
+
margin-top: 0.5rem;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
h5 {
|
|
227
|
+
margin-top: 0.5rem;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
h6 {
|
|
231
|
+
font-weight: 600;
|
|
232
|
+
margin-top: 0.5rem;
|
|
233
|
+
|
|
234
|
+
span {
|
|
235
|
+
font-family: sans-serif;
|
|
236
|
+
font-weight: 400;
|
|
237
|
+
font-size: 0.95rem;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
</style>
|
src/pages/index.astro
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Image } from 'astro:assets';
|
|
3
|
+
import Layout from '@/layouts/Base.astro';
|
|
4
|
+
import Slide from '@/components/Slide.astro';
|
|
5
|
+
import onlyBiblePng from '@/assets/images/app_icon.png';
|
|
6
|
+
import rustPng from '@/assets/logos/rust.png';
|
|
7
|
+
import pyrosshPng from '@/assets/logos/pyrossh.png';
|
|
8
|
+
import stats from '@/assets/logos/stats.png';
|
|
9
|
+
import code from '@/assets/logos/code.png';
|
|
10
|
+
import helix from '@/assets/logos/helix.png';
|
|
11
|
+
import nu from '@/assets/logos/nu.png';
|
|
12
|
+
import iterm from '@/assets/logos/iterm.png';
|
|
13
|
+
import zellij from '@/assets/logos/zellij.png';
|
|
14
|
+
import inkscape from '@/assets/logos/inkscape.png';
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
h2 {
|
|
19
|
+
font-size: 1.5rem;
|
|
20
|
+
font-weight: 600;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
section {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
margin-top: 1.5rem;
|
|
27
|
+
margin-bottom: 1rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.soft-link {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: row;
|
|
33
|
+
align-items: center;
|
|
34
|
+
text-align: left;
|
|
35
|
+
|
|
36
|
+
& > div {
|
|
37
|
+
flex: 1;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.p-0\.5 {
|
|
42
|
+
/* padding: 0.125rem; */
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.rounded-md {
|
|
46
|
+
border-radius: 0.375rem;
|
|
47
|
+
}
|
|
48
|
+
</style>
|
|
49
|
+
|
|
50
|
+
<Layout>
|
|
51
|
+
<div class="mx-auto mb-10">
|
|
52
|
+
<div>
|
|
53
|
+
<h1 class="text-3xl font-bold mb-4">Hello!</h1>
|
|
54
|
+
<p>
|
|
55
|
+
<a
|
|
56
|
+
class="underline"
|
|
57
|
+
href="https://www.linkedin.com/in/pyrossh"
|
|
58
|
+
target="_blank"
|
|
59
|
+
rel="noopener noreferrer"
|
|
60
|
+
>
|
|
61
|
+
<strong>I’m</strong>
|
|
62
|
+
</a>
|
|
63
|
+
a full stack developer based out of Bangalore, India and have worked for startups and enterprises
|
|
64
|
+
that focus on products in the healthcare and finance domains. I like to build frameworks and
|
|
65
|
+
automate common tasks to make it easier to develop applications.
|
|
66
|
+
</p>
|
|
67
|
+
<p>
|
|
68
|
+
I enjoy working on open-source projects, and during the last decade, I've created a number
|
|
69
|
+
of projects that are widely used.
|
|
70
|
+
</p>
|
|
71
|
+
<div>
|
|
72
|
+
<section>
|
|
73
|
+
<div class="flex items-center mb-4">
|
|
74
|
+
<h2>Projects</h2>
|
|
75
|
+
</div>
|
|
76
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-8">
|
|
77
|
+
<Slide title="rust-embed" link="https://git.sr.ht/~pyrossh/rust-embed">
|
|
78
|
+
<Image slot="icon" class="mr-2 w-9 rounded-xl" src={rustPng} alt="rust embed" />
|
|
79
|
+
<p>
|
|
80
|
+
A rust proc-macro which loads files into the rust binary at compile time during
|
|
81
|
+
release and loads the file from the fs during dev
|
|
82
|
+
</p>
|
|
83
|
+
</Slide>
|
|
84
|
+
<Slide title="pyrossh.dev" link="https://git.sr.ht/~pyrossh/website">
|
|
85
|
+
<Image
|
|
86
|
+
slot="icon"
|
|
87
|
+
class="mr-2 w-9 rounded-xl"
|
|
88
|
+
src={pyrosshPng}
|
|
89
|
+
alt="pyrossh website"
|
|
90
|
+
/>
|
|
91
|
+
<p>
|
|
92
|
+
木 Personal website of pyrossh. Built with
|
|
93
|
+
<span class="*:underline">
|
|
94
|
+
<a href="https://astro.build/" target="_blank" rel="noopener noreferrer"
|
|
95
|
+
>astrojs</a
|
|
96
|
+
>,
|
|
97
|
+
<a href="https://shiki.matsu.io/" target="_blank" rel="noopener noreferrer"
|
|
98
|
+
>shiki</a
|
|
99
|
+
>,
|
|
100
|
+
<a href="https://vitejs.dev/" target="_blank" rel="noopener noreferrer">vite</a>.
|
|
101
|
+
</span>
|
|
102
|
+
</p>
|
|
103
|
+
</Slide>
|
|
104
|
+
<Slide title="pacman" link="https://git.sr.ht/~pyrossh/plum">
|
|
105
|
+
<span slot="icon" class="text-4xl mr-2">👾</span>
|
|
106
|
+
<p>
|
|
107
|
+
A statically typed, imperative programming language with ADT's inspired by rust,
|
|
108
|
+
haskell.
|
|
109
|
+
</p>
|
|
110
|
+
</Slide>
|
|
111
|
+
<Slide title="Only Bible App" link="/only-bible-app" isExternal={false}>
|
|
112
|
+
<Image
|
|
113
|
+
slot="icon"
|
|
114
|
+
class="mr-2 w-9 rounded-xl"
|
|
115
|
+
src={onlyBiblePng}
|
|
116
|
+
alt="Only Bible App"
|
|
117
|
+
/>
|
|
118
|
+
<p>
|
|
119
|
+
The only bible app you will ever need. No ads, No in-app purchases, No distractions.
|
|
120
|
+
Works completely offline.
|
|
121
|
+
</p>
|
|
122
|
+
</Slide>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-8">
|
|
126
|
+
<section>
|
|
127
|
+
<div class="flex items-center">
|
|
128
|
+
<h2>Interests</h2>
|
|
129
|
+
</div>
|
|
130
|
+
<ul class="grid gap-2 grid-cols-3 text-center mt-4 *:bg-slate-100 *:p-1">
|
|
131
|
+
<li>HTML</li>
|
|
132
|
+
<li>CSS</li>
|
|
133
|
+
<li>Javascript</li>
|
|
134
|
+
<li>SQL</li>
|
|
135
|
+
<li>Go</li>
|
|
136
|
+
<li>Zig</li>
|
|
137
|
+
<li>Kotlin</li>
|
|
138
|
+
<li>React</li>
|
|
139
|
+
<li>Expo</li>
|
|
140
|
+
<li>Bun</li>
|
|
141
|
+
<li>MicroZig</li>
|
|
142
|
+
<li>Kaluma</li>
|
|
143
|
+
<li>K8s</li>
|
|
144
|
+
<li>Knative</li>
|
|
145
|
+
<li>Iceberg</li>
|
|
146
|
+
</ul>
|
|
147
|
+
</section>
|
|
148
|
+
<section>
|
|
149
|
+
<div class="flex items-center">
|
|
150
|
+
<h2>Contact</h2>
|
|
151
|
+
</div>
|
|
152
|
+
<ul
|
|
153
|
+
class="grid gap-2 grid-cols-1 text-left mt-4 *:bg-slate-100 *:p-2 *:flex *:flex-col *:items-baseline *:sm:flex-row"
|
|
154
|
+
>
|
|
155
|
+
<li>
|
|
156
|
+
<strong class="mr-2">Email:</strong>
|
|
157
|
+
<span>[email protected]</span>
|
|
158
|
+
</li>
|
|
159
|
+
<li>
|
|
160
|
+
<strong class="mr-2">Sourcehut:</strong>
|
|
161
|
+
<a class="text-blue-900" href="https://git.sr.ht/~pyrossh/">
|
|
162
|
+
https://git.sr.ht/~pyrossh/
|
|
163
|
+
</a>
|
|
164
|
+
</li>
|
|
165
|
+
<li>
|
|
166
|
+
<strong class="mr-2">LinkedIn:</strong>
|
|
167
|
+
<a class="text-blue-900" href="https://www.linkedin.com/in/peter-john-in">
|
|
168
|
+
https://www.linkedin.com/in/pyrossh
|
|
169
|
+
</a>
|
|
170
|
+
</li>
|
|
171
|
+
</ul>
|
|
172
|
+
</section>
|
|
173
|
+
</div>
|
|
174
|
+
<section>
|
|
175
|
+
<div class="flex items-center">
|
|
176
|
+
<h2>Tools</h2>
|
|
177
|
+
</div>
|
|
178
|
+
<ul class="grid gap-2 grid-cols-3 md:grid-cols-7 text-center mt-4 *:bg-slate-100 *:p-1">
|
|
179
|
+
<li>
|
|
180
|
+
<a
|
|
181
|
+
class="soft-link"
|
|
182
|
+
href="https://github.com/exelban/stats"
|
|
183
|
+
target="_blank"
|
|
184
|
+
rel="noopener noreferrer"
|
|
185
|
+
>
|
|
186
|
+
<div>Stats</div>
|
|
187
|
+
<Image src={stats} alt="Stats" width="32" />
|
|
188
|
+
</a>
|
|
189
|
+
</li>
|
|
190
|
+
<li>
|
|
191
|
+
<a
|
|
192
|
+
class="soft-link"
|
|
193
|
+
href="https://github.com/microsoft/vscode"
|
|
194
|
+
target="_blank"
|
|
195
|
+
rel="noopener noreferrer"
|
|
196
|
+
>
|
|
197
|
+
<div>VS Code</div>
|
|
198
|
+
<Image src={code} alt="VS Code" width="32" />
|
|
199
|
+
</a>
|
|
200
|
+
</li>
|
|
201
|
+
<li>
|
|
202
|
+
<a
|
|
203
|
+
class="soft-link"
|
|
204
|
+
href="https://github.com/helix-editor/helix"
|
|
205
|
+
target="_blank"
|
|
206
|
+
rel="noopener noreferrer"
|
|
207
|
+
>
|
|
208
|
+
<div>Helix</div>
|
|
209
|
+
<Image src={helix} alt="Helix" width="32" />
|
|
210
|
+
</a>
|
|
211
|
+
</li>
|
|
212
|
+
<li>
|
|
213
|
+
<a
|
|
214
|
+
class="soft-link"
|
|
215
|
+
href="https://github.com/nushell/nushell"
|
|
216
|
+
target="_blank"
|
|
217
|
+
rel="noopener noreferrer"
|
|
218
|
+
>
|
|
219
|
+
<div>Nushell</div>
|
|
220
|
+
<Image class="p-0.5 rounded-md" src={nu} alt="nu-shell" width="32" />
|
|
221
|
+
</a>
|
|
222
|
+
</li>
|
|
223
|
+
<li>
|
|
224
|
+
<a
|
|
225
|
+
class="soft-link"
|
|
226
|
+
href="https://github.com/gnachman/iTerm2"
|
|
227
|
+
target="_blank"
|
|
228
|
+
rel="noopener noreferrer"
|
|
229
|
+
>
|
|
230
|
+
<div>iTerm2</div>
|
|
231
|
+
<Image src={iterm} alt="iterm2" width="32" />
|
|
232
|
+
</a>
|
|
233
|
+
</li>
|
|
234
|
+
<li>
|
|
235
|
+
<a
|
|
236
|
+
class="soft-link"
|
|
237
|
+
href="https://zellij.dev/"
|
|
238
|
+
target="_blank"
|
|
239
|
+
rel="noopener noreferrer"
|
|
240
|
+
>
|
|
241
|
+
<div>Zellij</div>
|
|
242
|
+
<Image class="w-7 p-0.5" src={zellij} alt="zellij" width="32" />
|
|
243
|
+
</a>
|
|
244
|
+
</li>
|
|
245
|
+
|
|
246
|
+
<li>
|
|
247
|
+
<a
|
|
248
|
+
class="soft-link"
|
|
249
|
+
href="https://inkscape.org/"
|
|
250
|
+
target="_blank"
|
|
251
|
+
rel="noopener noreferrer"
|
|
252
|
+
>
|
|
253
|
+
<div>Inkscape</div>
|
|
254
|
+
<Image src={inkscape} alt="inkscape" width="32" />
|
|
255
|
+
</a>
|
|
256
|
+
</li>
|
|
257
|
+
</ul>
|
|
258
|
+
</section>
|
|
259
|
+
</section>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
</Layout>
|
src/pages/posts/[...slug].astro
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { type CollectionEntry, getCollection } from 'astro:content';
|
|
3
|
+
import { render } from 'astro:content';
|
|
4
|
+
import Layout from '@/layouts/Base.astro';
|
|
5
|
+
import FormattedDate from '@/components/FormattedDate.astro';
|
|
6
|
+
|
|
7
|
+
export async function getStaticPaths() {
|
|
8
|
+
const posts = await getCollection('blog');
|
|
9
|
+
return posts.map((post) => ({
|
|
10
|
+
params: { slug: post.id },
|
|
11
|
+
props: post,
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
type Props = CollectionEntry<'blog'>;
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
data: { title, description, pubDate, updatedDate, heroImage },
|
|
18
|
+
} = Astro.props;
|
|
19
|
+
const { Content } = await render(Astro.props);
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<Layout>
|
|
23
|
+
<article>
|
|
24
|
+
<!-- <div class="hero-image">
|
|
25
|
+
{heroImage && <img width={1020} height={510} src={heroImage} alt="" />}
|
|
26
|
+
</div> -->
|
|
27
|
+
<div class="title">
|
|
28
|
+
<div class="date">
|
|
29
|
+
<FormattedDate date={pubDate} />
|
|
30
|
+
{
|
|
31
|
+
updatedDate && (
|
|
32
|
+
<div class="last-updated-on">
|
|
33
|
+
Last updated on <FormattedDate date={updatedDate} />
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
</div>
|
|
38
|
+
<h1>{title}</h1>
|
|
39
|
+
<hr />
|
|
40
|
+
</div>
|
|
41
|
+
<Content />
|
|
42
|
+
</article>
|
|
43
|
+
</Layout>
|
|
44
|
+
<style>
|
|
45
|
+
article {
|
|
46
|
+
p {
|
|
47
|
+
padding-bottom: 20px;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
.hero-image {
|
|
51
|
+
width: 100%;
|
|
52
|
+
}
|
|
53
|
+
.hero-image img {
|
|
54
|
+
display: block;
|
|
55
|
+
margin: 0 auto;
|
|
56
|
+
border-radius: 12px;
|
|
57
|
+
box-shadow: var(--box-shadow);
|
|
58
|
+
}
|
|
59
|
+
.title {
|
|
60
|
+
margin-bottom: 1em;
|
|
61
|
+
padding: 1em 0;
|
|
62
|
+
text-align: center;
|
|
63
|
+
line-height: 1;
|
|
64
|
+
}
|
|
65
|
+
.title h1 {
|
|
66
|
+
margin: 0 0 0.5em 0;
|
|
67
|
+
}
|
|
68
|
+
.date {
|
|
69
|
+
margin-bottom: 0.5em;
|
|
70
|
+
color: rgb(var(--gray));
|
|
71
|
+
}
|
|
72
|
+
.last-updated-on {
|
|
73
|
+
font-style: italic;
|
|
74
|
+
}
|
|
75
|
+
</style>
|
src/pages/posts/index.astro
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { getCollection } from 'astro:content';
|
|
3
|
+
import FormattedDate from '../../components/FormattedDate.astro';
|
|
4
|
+
import Layout from '@/layouts/Base.astro';
|
|
5
|
+
|
|
6
|
+
const posts = (await getCollection('blog')).sort(
|
|
7
|
+
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
|
|
8
|
+
);
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<Layout>
|
|
12
|
+
<h1 class="font-bold text-3xl">Posts</h1>
|
|
13
|
+
<div class="container">
|
|
14
|
+
<ul class="flex flex-col">
|
|
15
|
+
{
|
|
16
|
+
posts.map((post) => (
|
|
17
|
+
<li class="grid grid-cols-1 sm:grid-cols-2 gap-3 justify-start items-end mt-5 leading-6">
|
|
18
|
+
<div class="flex flex-col">
|
|
19
|
+
<a class="text-black underline underline-offset-4" href={`/posts/${post.id}`}>
|
|
20
|
+
{post.data.title}
|
|
21
|
+
</a>
|
|
22
|
+
{/* <span class="hover:cursor-default">{post.data.}</span> */}
|
|
23
|
+
</div>
|
|
24
|
+
<span class="flex flex-1 justify-end sm:ml-4 text-md text-gray-900">
|
|
25
|
+
<FormattedDate date={post.data.pubDate} />
|
|
26
|
+
</span>
|
|
27
|
+
{/* <a href={`/blog/${post.id}/`}>
|
|
28
|
+
<img width={720} height={360} src={post.data.heroImage} alt="" />
|
|
29
|
+
<h4 class="title">{post.data.title}</h4>
|
|
30
|
+
<p class="date">
|
|
31
|
+
<FormattedDate date={post.data.pubDate} />
|
|
32
|
+
</p>
|
|
33
|
+
</a> */}
|
|
34
|
+
</li>
|
|
35
|
+
))
|
|
36
|
+
}
|
|
37
|
+
</ul>
|
|
38
|
+
</div>
|
|
39
|
+
</Layout>
|
|
40
|
+
<style>
|
|
41
|
+
.container {
|
|
42
|
+
display: flex;
|
|
43
|
+
float: left;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
src/pages/rss.xml.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import rss from '@astrojs/rss';
|
|
2
|
+
import { getCollection } from 'astro:content';
|
|
3
|
+
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
|
|
4
|
+
|
|
5
|
+
export async function GET(context) {
|
|
6
|
+
const posts = await getCollection('blog');
|
|
7
|
+
return rss({
|
|
8
|
+
title: SITE_TITLE,
|
|
9
|
+
description: SITE_DESCRIPTION,
|
|
10
|
+
site: context.site,
|
|
11
|
+
items: posts.map((post) => ({
|
|
12
|
+
...post.data,
|
|
13
|
+
link: `/blog/${post.id}/`,
|
|
14
|
+
})),
|
|
15
|
+
});
|
|
16
|
+
}
|
src/routes/cv/+page.svelte
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
<svelte:head>
|
|
2
|
-
<title>pyrossh | 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
|
-
<h6>John Lewis <span>(Mar '21 - Aug '24)</span></h6>
|
|
19
|
-
<ul class="*:list-disc">
|
|
20
|
-
<li>
|
|
21
|
-
Built a quiz memory game with leaderboard scoring to improve engagement during
|
|
22
|
-
Christmas
|
|
23
|
-
</li>
|
|
24
|
-
<li>
|
|
25
|
-
Implemented new features for customer self-serve actions in returns, cancellations,
|
|
26
|
-
tracking
|
|
27
|
-
</li>
|
|
28
|
-
<li>
|
|
29
|
-
Refactored the old self-serve React app to use Nextjs and removed a large dependency
|
|
30
|
-
on redux
|
|
31
|
-
</li>
|
|
32
|
-
<li>
|
|
33
|
-
Ran many experiments in the customer services and order pages to improve our metrics
|
|
34
|
-
and reduce contacts
|
|
35
|
-
</li>
|
|
36
|
-
<li>
|
|
37
|
-
Built the new Product Description Page (PDP) for Simple Carpets using a micro frontend
|
|
38
|
-
architecture
|
|
39
|
-
</li>
|
|
40
|
-
<li>
|
|
41
|
-
<b>Technologies & Tools</b>: Nodejs, Nextjs, Reactjs, Kotlin, K8s, Grafana, Kibana,
|
|
42
|
-
Firestore, Google Sheets API, Monetate, Adobe Analytics, Scene7, Adobe AEM
|
|
43
|
-
</li>
|
|
44
|
-
</ul>
|
|
45
|
-
</li>
|
|
46
|
-
<li>
|
|
47
|
-
<h6>iOWNA <span>(Mar '20 - Mar '21)</span></h6>
|
|
48
|
-
<ul class="*:list-disc">
|
|
49
|
-
<li>Built a Content Editor for curators to create content on our platform</li>
|
|
50
|
-
<li>
|
|
51
|
-
Built the iOWNA crossplatform app in react-native that works in android, ios, and web
|
|
52
|
-
using one codebase.
|
|
53
|
-
</li>
|
|
54
|
-
<li>Implemented Admin specific functionalities in the web app</li>
|
|
55
|
-
<li>Implemented an in-app OTA update method using expo and semantic versioning.</li>
|
|
56
|
-
<li>Built the iOWNA marketing website</li>
|
|
57
|
-
<li>
|
|
58
|
-
Built the Health Questionnaire clinician/patient feedback form feature with push
|
|
59
|
-
notifications
|
|
60
|
-
</li>
|
|
61
|
-
<li>
|
|
62
|
-
<b>Technologies & Tools</b>: Go, Javascript, React Native, Expo, GraphQL, Serverless,
|
|
63
|
-
AppSync, Cognito, Dynamodb, API Gateway, Lambda, Cloudformation
|
|
64
|
-
</li>
|
|
65
|
-
</ul>
|
|
66
|
-
</li>
|
|
67
|
-
<li>
|
|
68
|
-
<h6>Zeta <span>(Nov '19 - Feb '20)</span></h6>
|
|
69
|
-
<ul class="*:list-disc">
|
|
70
|
-
<li>
|
|
71
|
-
Added multiple download formats (pdf,html,xlsx) for reports in the Reporting Center
|
|
72
|
-
</li>
|
|
73
|
-
<li>
|
|
74
|
-
Created a Groovy Script to automate creating ACL in sandbox authorization framework
|
|
75
|
-
</li>
|
|
76
|
-
<li>Integrated Camunda Workflow Engine into Zeta services in Operations Center</li>
|
|
77
|
-
<li>Built a few workflows on Camunda and integrated it with some internal services</li>
|
|
78
|
-
<li>
|
|
79
|
-
Built a custom k8s CRD using the operator framework to automate creating ACL in
|
|
80
|
-
sandbox using custom resources
|
|
81
|
-
</li>
|
|
82
|
-
<li>
|
|
83
|
-
<b>Technologies & Tools</b>: Go, Java, Springboot, Camunda, Postgres, Docker, K8s
|
|
84
|
-
</li>
|
|
85
|
-
</ul>
|
|
86
|
-
</li>
|
|
87
|
-
<li>
|
|
88
|
-
<h6>Lifebox <span>(Oct '18 - Oct '19)</span></h6>
|
|
89
|
-
<ul class="*:list-disc">
|
|
90
|
-
<li>Added search functionality to the hospital procedure codes</li>
|
|
91
|
-
<li>
|
|
92
|
-
Converted the Health Questionnaire from json to native go code making it easier to
|
|
93
|
-
make changes to it
|
|
94
|
-
</li>
|
|
95
|
-
<li>
|
|
96
|
-
Integrated with SAP using HL7 message format to create patients, episodes,
|
|
97
|
-
schedule/cancel procedures
|
|
98
|
-
</li>
|
|
99
|
-
<li>Built the Patient Document repository for uploading, downloading patient files</li>
|
|
100
|
-
<li>Built the patients online reports view using the data from SAP</li>
|
|
101
|
-
<li>
|
|
102
|
-
<b>Technologies & Tools</b>: Go, Javascript, Reactjs, K6, Serverless, Grafana,
|
|
103
|
-
Cognito, Dynamodb, API Gateway , Lambda, GraphQL, Cloudformation, SQLite3
|
|
104
|
-
</li>
|
|
105
|
-
</ul>
|
|
106
|
-
</li>
|
|
107
|
-
</ul>
|
|
108
|
-
</div>
|
|
109
|
-
</section>
|
|
110
|
-
<section>
|
|
111
|
-
<h3>Numberz</h3>
|
|
112
|
-
<h4>Full Stack Developer, Sept 2016 - Oct 2018</h4>
|
|
113
|
-
<h5>
|
|
114
|
-
Numberz integrates banking with your day-2-day business work-flows freeing up a lot of effort,
|
|
115
|
-
time and heart-burn, to help your business grow.
|
|
116
|
-
</h5>
|
|
117
|
-
<ul class="*:list-disc">
|
|
118
|
-
<li>Implemented new features and fixed bugs on the numberz android app</li>
|
|
119
|
-
<li>Integrated numberz with Tally ERP (export and import of sales, purchases)</li>
|
|
120
|
-
<li>
|
|
121
|
-
Implemented CI and Devops within out system to ease our deployment process using docker and
|
|
122
|
-
docker-compose
|
|
123
|
-
</li>
|
|
124
|
-
<li>
|
|
125
|
-
Created a slack bot called deploybot which was used to deploy our microservices to our
|
|
126
|
-
servers
|
|
127
|
-
</li>
|
|
128
|
-
<li>Started tech talks on Thursdays to discuss cutting edge technologies</li>
|
|
129
|
-
<li>Architected and built the Notification Service using rabbitmq and nodejs</li>
|
|
130
|
-
<li>Built the Multi-User and Multi-Company Features</li>
|
|
131
|
-
<li>
|
|
132
|
-
Implemented and lead a team on integration with the GSTN System so that customers could file
|
|
133
|
-
their GST Taxes within our product
|
|
134
|
-
</li>
|
|
135
|
-
<li>Architected and built the numberz Identity Management Service(IMS)</li>
|
|
136
|
-
<li>Architected our new product called the Numberz Accounts Receivable (AR)</li>
|
|
137
|
-
<li>Laid down the architecture for the frontend and backend</li>
|
|
138
|
-
<li>
|
|
139
|
-
Built these core features for our new AR Product - Auto Reminders, Manual Reminders, User
|
|
140
|
-
Management, Cash Discounting, CFO Dashboard Metrics
|
|
141
|
-
</li>
|
|
142
|
-
<li>
|
|
143
|
-
<b>Technologies & Tools</b>: Nodejs, Mongodb, Postgres, GraphQL, Ansible, K8s, Typescript,
|
|
144
|
-
Reactjs
|
|
145
|
-
</li>
|
|
146
|
-
</ul>
|
|
147
|
-
</section>
|
|
148
|
-
<section>
|
|
149
|
-
<h3>Playlyfe</h3>
|
|
150
|
-
<h4>Full Stack Developer, Apr 2014 - Sept 2016</h4>
|
|
151
|
-
<h5>
|
|
152
|
-
Playlyfe is an online Gamification Platform which empowers anyone to design and implement a
|
|
153
|
-
gamified system.
|
|
154
|
-
</h5>
|
|
155
|
-
<ul class="*:list-disc">
|
|
156
|
-
<li>Built the Playlyfe Hybrid Mobile app using Phonegap for Android and iOS</li>
|
|
157
|
-
<li>Built the leaderboard system using Mongodb, Redis and Couchbase as the datastore</li>
|
|
158
|
-
<li>Migration of data from v1 to v2 of the API</li>
|
|
159
|
-
<li>Built SDKs for the Playlyfe v2 API in C#, Java, Python, Ruby, PHP, Nodejs, Gos</li>
|
|
160
|
-
<li>Maintained the job server and wrote most of the background jobs</li>
|
|
161
|
-
<li>
|
|
162
|
-
Added documentation to most of the REST API and created the Developer Console which was Like
|
|
163
|
-
Swagger UI
|
|
164
|
-
</li>
|
|
165
|
-
<li>Integrated our REST API in Leanosphere's LMS</li>
|
|
166
|
-
<li>Integrated the REST API in Knolskape's product Aktivlearn LMS</li>
|
|
167
|
-
<li>Integrated the REST API in Linkstreet's LMS</li>
|
|
168
|
-
<li>
|
|
169
|
-
Integrated the REST API in Moodle LMS by creating an admin plugin to add Gamification
|
|
170
|
-
features
|
|
171
|
-
</li>
|
|
172
|
-
<li>Rebuilt the core platform in golang for performance and developement speed</li>
|
|
173
|
-
<li>Built the GraphQL API for our cutting edge product Catalyst</li>
|
|
174
|
-
<li>Convinced the boss to create our own scripting language plscript for our rule engine.</li>
|
|
175
|
-
<li>Build a REST API for our product catalyst for a POC with Vodafone</li>
|
|
176
|
-
<li>
|
|
177
|
-
Built the Quiz, Review, Match, Tournament features in Catalyst for a major project with HP
|
|
178
|
-
</li>
|
|
179
|
-
<li>Added gamification features to Saudi Matches a popular game tracking app</li>
|
|
180
|
-
<li>
|
|
181
|
-
<b>Technologies & Tools</b>: Nodejs, Coffeescript, Angularjs, Mongodb, Couchbase, Redis,
|
|
182
|
-
Seaweedfs, Postgres, Golang, GraphQL, Relay, React
|
|
183
|
-
</li>
|
|
184
|
-
</ul>
|
|
185
|
-
</section>
|
|
186
|
-
</div>
|
|
187
|
-
|
|
188
|
-
<style>
|
|
189
|
-
b {
|
|
190
|
-
font-weight: 600;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
ul {
|
|
194
|
-
margin: 0.5rem;
|
|
195
|
-
padding-left: 1rem;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
li {
|
|
199
|
-
list-style-type: disc;
|
|
200
|
-
list-style-position: outside;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
h3 {
|
|
204
|
-
font-weight: 700;
|
|
205
|
-
font-size: 1.2rem;
|
|
206
|
-
margin-top: 0.5rem;
|
|
207
|
-
margin-bottom: 0.5rem;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
h4 {
|
|
211
|
-
font-weight: 600;
|
|
212
|
-
margin-top: 0.5rem;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
h5 {
|
|
216
|
-
margin-top: 0.5rem;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
h6 {
|
|
220
|
-
font-weight: 600;
|
|
221
|
-
margin-top: 0.5rem;
|
|
222
|
-
|
|
223
|
-
span {
|
|
224
|
-
font-family: sans-serif;
|
|
225
|
-
font-weight: 400;
|
|
226
|
-
font-size: 0.95rem;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
</style>
|
src/styles/global.css
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
:root {
|
|
4
|
+
--color-accent: #F1FA8C;
|
|
5
|
+
--color-accent-dark: #000D8A;
|
|
6
|
+
--color-black: #000000;
|
|
7
|
+
--color-white: #FFFFFF;
|
|
8
|
+
--gray: 96, 115, 159;
|
|
9
|
+
--gray-light: 229, 233, 240;
|
|
10
|
+
--gray-dark: 34, 41, 57;
|
|
11
|
+
--gray-gradient: rgba(var(--gray-light), 50%), #fff;
|
|
12
|
+
--box-shadow:
|
|
13
|
+
0 2px 6px rgba(var(--gray), 25%), 0 8px 24px rgba(var(--gray), 33%),
|
|
14
|
+
0 16px 32px rgba(var(--gray), 33%);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* body {
|
|
18
|
+
margin: 0;
|
|
19
|
+
padding: 0;
|
|
20
|
+
text-align: left;
|
|
21
|
+
background: linear-gradient(var(--gray-gradient)) no-repeat;
|
|
22
|
+
background-size: 100% 600px;
|
|
23
|
+
word-wrap: break-word;
|
|
24
|
+
overflow-wrap: break-word;
|
|
25
|
+
color: rgb(var(--gray-dark));
|
|
26
|
+
font-size: 20px;
|
|
27
|
+
line-height: 1.7;
|
|
28
|
+
} */
|
|
29
|
+
|
|
30
|
+
/* h1,
|
|
31
|
+
h2,
|
|
32
|
+
h3,
|
|
33
|
+
h4,
|
|
34
|
+
h5,
|
|
35
|
+
h6 {
|
|
36
|
+
margin: 0 0 0.5rem 0;
|
|
37
|
+
color: rgb(var(--black));
|
|
38
|
+
line-height: 1.2;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
h1 {
|
|
42
|
+
font-size: 3.052em;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
h2 {
|
|
46
|
+
font-size: 2.441em;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
h3 {
|
|
50
|
+
font-size: 1.953em;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
h4 {
|
|
54
|
+
font-size: 1.563em;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
h5 {
|
|
58
|
+
font-size: 1.25em;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
strong,
|
|
62
|
+
b {
|
|
63
|
+
font-weight: 700;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
a {
|
|
67
|
+
color: var(--color-black);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
a:hover {
|
|
71
|
+
color: var(--accent);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
p {
|
|
75
|
+
margin-bottom: 1em;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.prose p {
|
|
79
|
+
margin-bottom: 2em;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
textarea {
|
|
83
|
+
width: 100%;
|
|
84
|
+
font-size: 16px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
input {
|
|
88
|
+
font-size: 16px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
table {
|
|
92
|
+
width: 100%;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
img {
|
|
96
|
+
max-width: 100%;
|
|
97
|
+
height: auto;
|
|
98
|
+
border-radius: 8px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
code {
|
|
102
|
+
padding: 2px 5px;
|
|
103
|
+
background-color: rgb(var(--gray-light));
|
|
104
|
+
border-radius: 2px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
pre {
|
|
108
|
+
padding: 1.5em;
|
|
109
|
+
border-radius: 8px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
pre>code {
|
|
113
|
+
all: unset;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
blockquote {
|
|
117
|
+
border-left: 4px solid var(--accent);
|
|
118
|
+
padding: 0 0 0 20px;
|
|
119
|
+
margin: 0px;
|
|
120
|
+
font-size: 1.333em;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
hr {
|
|
124
|
+
border: none;
|
|
125
|
+
border-top: 1px solid rgb(var(--gray-light));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@media (max-width: 720px) {
|
|
129
|
+
body {
|
|
130
|
+
font-size: 18px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
main {
|
|
134
|
+
padding: 1em;
|
|
135
|
+
}
|
|
136
|
+
} */
|
|
137
|
+
|
|
138
|
+
.wrapper {
|
|
139
|
+
width: calc(95ex - (1em * 2));
|
|
140
|
+
margin-right: auto;
|
|
141
|
+
margin-left: auto;
|
|
142
|
+
padding-left: 1em;
|
|
143
|
+
padding-right: 1em;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@media (max-width: 720px) {
|
|
147
|
+
.wrapper {
|
|
148
|
+
width: 100%;
|
|
149
|
+
}
|
|
150
|
+
}
|
{src → src2}/app.css
RENAMED
|
File without changes
|
{src → src2}/app.d.ts
RENAMED
|
File without changes
|
{src → src2}/app.html
RENAMED
|
File without changes
|
{src → src2}/index.test.js
RENAMED
|
File without changes
|
{src → src2}/routes/+error.svelte
RENAMED
|
File without changes
|
{src → src2}/routes/+layout.js
RENAMED
|
File without changes
|
{src → src2}/routes/+layout.svelte
RENAMED
|
@@ -17,28 +17,8 @@
|
|
|
17
17
|
let isAppPage = $derived($page.url.pathname.includes('only-bible-app'));
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
|
-
<svelte:head>
|
|
21
|
-
<meta name="author" content="pyrossh" />
|
|
22
|
-
<meta name="keywords" content="pyrossh.dev,pyrossh,svelte,website" />
|
|
23
|
-
<link rel="canonical" href={url} />
|
|
24
|
-
<meta property="og:site_name" content="pyrossh.dev" />
|
|
25
|
-
<meta property="og:type" content="website" />
|
|
26
|
-
<meta property="og:url" content={url} />
|
|
27
|
-
</svelte:head>
|
|
20
|
+
<svelte:head></svelte:head>
|
|
28
|
-
{#if !isAppPage}
|
|
21
|
+
{#if !isAppPage}{:else}
|
|
29
|
-
<div class="flex flex-1 flex-col">
|
|
30
|
-
<Header />
|
|
31
|
-
<main class="wrapper bg-white">
|
|
32
|
-
<div class="flex flex-1 flex-row">
|
|
33
|
-
<div class="flex flex-1 flex-row my-4">
|
|
34
|
-
<!-- {@render children()} -->
|
|
35
|
-
{@render children?.()}
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
</main>
|
|
39
|
-
<Footer />
|
|
40
|
-
</div>
|
|
41
|
-
{:else}
|
|
42
22
|
{@render children?.()}
|
|
43
23
|
{/if}
|
|
44
24
|
|
{src → src2}/routes/+page.svelte
RENAMED
|
@@ -243,32 +243,3 @@
|
|
|
243
243
|
</div>
|
|
244
244
|
</div>
|
|
245
245
|
</div>
|
|
246
|
-
|
|
247
|
-
<style>
|
|
248
|
-
h2 {
|
|
249
|
-
font-size: 1.5rem;
|
|
250
|
-
font-weight: 600;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
section {
|
|
254
|
-
display: flex;
|
|
255
|
-
flex-direction: column;
|
|
256
|
-
margin-top: 1.5rem;
|
|
257
|
-
margin-bottom: 1rem;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.soft-link {
|
|
261
|
-
display: flex;
|
|
262
|
-
flex-direction: row;
|
|
263
|
-
align-items: center;
|
|
264
|
-
text-align: left;
|
|
265
|
-
|
|
266
|
-
& > div {
|
|
267
|
-
flex: 1;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
.soft-icon {
|
|
272
|
-
width: 32px;
|
|
273
|
-
}
|
|
274
|
-
</style>
|
src2/routes/cv/+page.svelte
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svelte:head>
|
|
2
|
+
<title>pyrossh | cv</title>
|
|
3
|
+
<meta name="description" content="Peter John's CV" />
|
|
4
|
+
</svelte:head>
|
{src → src2}/routes/only-bible-app/+layout.svelte
RENAMED
|
File without changes
|
{src → src2}/routes/only-bible-app/+page.svelte
RENAMED
|
File without changes
|
{src → src2}/routes/only-bible-app/privacy-policy/+page.svelte
RENAMED
|
File without changes
|
{src → src2}/routes/only-bible-app/terms-and-conditions/+page.svelte
RENAMED
|
File without changes
|
{src → src2}/routes/posts/+page.js
RENAMED
|
File without changes
|
{src → src2}/routes/posts/+page.svelte
RENAMED
|
File without changes
|
{src → src2}/routes/posts/[slug]/+page.js
RENAMED
|
File without changes
|
{src → src2}/routes/posts/[slug]/+page.svelte
RENAMED
|
File without changes
|
{src → src2}/routes/sitemap.xml/+server.js
RENAMED
|
File without changes
|
{src → src2}/vite-env.d.ts
RENAMED
|
File without changes
|
tsconfig.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "astro/tsconfigs/strict",
|
|
3
|
+
"include": [".astro/types.d.ts", "**/*"],
|
|
4
|
+
"exclude": ["dist"],
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"strictNullChecks": true,
|
|
7
|
+
"baseUrl": ".",
|
|
8
|
+
"paths": {
|
|
9
|
+
"@/*": ["src/*"]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|