Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
56545bc3a3 | |||
a7d1cf28ba | |||
1517e81ef8 | |||
d78756f367 | |||
03f476f7a0 | |||
476203d81b | |||
6fdbb9079e |
4
.gitignore
vendored
4
.gitignore
vendored
@ -130,6 +130,4 @@ dist
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
.svelte-kit
|
||||
|
||||
build
|
||||
.svelte-kit
|
38
README.md
Normal file
38
README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# sv
|
||||
|
||||
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
||||
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npx sv create
|
||||
|
||||
# create a new project in my-app
|
||||
npx sv create my-app
|
||||
```
|
||||
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
@ -0,0 +1,13 @@
|
||||
services:
|
||||
nodejs:
|
||||
image: node:latest
|
||||
container_name: node_app
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ./:/app
|
||||
ports:
|
||||
- "80:5173"
|
||||
command: >
|
||||
sh -c "npm i -g npm@latest &&
|
||||
npm i &&
|
||||
npm run dev"
|
178
package-lock.json
generated
178
package-lock.json
generated
@ -13,23 +13,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.2.3",
|
||||
"@fontsource/abril-fatface": "^5.1.1",
|
||||
"@fontsource/inter": "^5.1.1",
|
||||
"@fontsource/playfair-display": "^5.1.1",
|
||||
"@fontsource/quicksand": "^5.1.1",
|
||||
"@fontsource/space-grotesk": "^5.1.1",
|
||||
"@iconify/json": "^2.2.293",
|
||||
"@skeletonlabs/skeleton": "^2.10.4",
|
||||
"@skeletonlabs/tw-plugin": "^0.4.0",
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/adapter-node": "^5.2.11",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"axios": "^1.8.1",
|
||||
"dylan-ipsum": "^1.1.0",
|
||||
"eslint": "^9.7.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.36.0",
|
||||
@ -643,41 +635,6 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/abril-fatface": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/abril-fatface/-/abril-fatface-5.1.1.tgz",
|
||||
"integrity": "sha512-5K7YdlFTk7zAdCkr7XbzqMDxxTQ3J/FE91w0dn89b7p8RuXmTDK5bQ9k7XXMFMHN4r90SvWnWboaKzbXQMLyjQ==",
|
||||
"dev": true,
|
||||
"license": "OFL-1.1"
|
||||
},
|
||||
"node_modules/@fontsource/inter": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.1.1.tgz",
|
||||
"integrity": "sha512-weN3E+rq0Xb3Z93VHJ+Rc7WOQX9ETJPTAJ+gDcaMHtjft67L58sfS65rAjC5tZUXQ2FdZ/V1/sSzCwZ6v05kJw==",
|
||||
"dev": true,
|
||||
"license": "OFL-1.1"
|
||||
},
|
||||
"node_modules/@fontsource/playfair-display": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/playfair-display/-/playfair-display-5.1.1.tgz",
|
||||
"integrity": "sha512-BCIovoAYzgs6UIve00tjutzEDJ+iP+nMOHQP6joSmheE3WGM7m8JU/btq/iUOjV9HK5E4F8NgzdRIPfi1kWzjA==",
|
||||
"dev": true,
|
||||
"license": "OFL-1.1"
|
||||
},
|
||||
"node_modules/@fontsource/quicksand": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/quicksand/-/quicksand-5.1.1.tgz",
|
||||
"integrity": "sha512-NnIL4yqpkn50GEpye7yztBmkkkQ5vjlVvMnjlkLQr/H8PXveUdaCdGIScd5yHvsc1qcTBwOaAtpz/YkDojwA1A==",
|
||||
"dev": true,
|
||||
"license": "OFL-1.1"
|
||||
},
|
||||
"node_modules/@fontsource/space-grotesk": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/space-grotesk/-/space-grotesk-5.1.1.tgz",
|
||||
"integrity": "sha512-6uOS8WhMEl6lbykGvkSjxRLs/1lDvfSKyXAau7ONVPzUYBmB1E+JQ3C0du7NDp75xUZ+330xPc9/ep8uFgIXBg==",
|
||||
"dev": true,
|
||||
"license": "OFL-1.1"
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
||||
@ -1392,16 +1349,6 @@
|
||||
"@sveltejs/kit": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-static": {
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.8.tgz",
|
||||
"integrity": "sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@sveltejs/kit": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/kit": {
|
||||
"version": "2.15.2",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.15.2.tgz",
|
||||
@ -1668,13 +1615,6 @@
|
||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.20",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
|
||||
@ -1713,18 +1653,6 @@
|
||||
"postcss": "^8.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz",
|
||||
"integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axobject-query": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||
@ -2015,19 +1943,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||
@ -2204,16 +2119,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
@ -2268,13 +2173,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/dylan-ipsum": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dylan-ipsum/-/dylan-ipsum-1.1.0.tgz",
|
||||
"integrity": "sha512-L/U6bSf63eovEtddaJTRyuG42/1Nq5R7blYOyoAD8NXPw+EimuynIL9Sgh7F1msVwlmvCAFdpeh6wXjJuQg76A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
@ -2341,22 +2239,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.21.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
||||
@ -2904,27 +2786,6 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
||||
@ -2942,22 +2803,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
|
||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
@ -3172,22 +3017,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
@ -4389,13 +4218,6 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
|
@ -12,23 +12,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.2.3",
|
||||
"@fontsource/abril-fatface": "^5.1.1",
|
||||
"@fontsource/inter": "^5.1.1",
|
||||
"@fontsource/playfair-display": "^5.1.1",
|
||||
"@fontsource/quicksand": "^5.1.1",
|
||||
"@fontsource/space-grotesk": "^5.1.1",
|
||||
"@iconify/json": "^2.2.293",
|
||||
"@skeletonlabs/skeleton": "^2.10.4",
|
||||
"@skeletonlabs/tw-plugin": "^0.4.0",
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/adapter-node": "^5.2.11",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
||||
"@tailwindcss/forms": "^0.5.10",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"axios": "^1.8.1",
|
||||
"dylan-ipsum": "^1.1.0",
|
||||
"eslint": "^9.7.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.36.0",
|
||||
|
24
src/app.css
24
src/app.css
@ -1,4 +1,24 @@
|
||||
/* Test */
|
||||
@import 'tailwindcss/base';
|
||||
@import 'tailwindcss/components';
|
||||
@import 'tailwindcss/utilities';
|
||||
@import 'tailwindcss/utilities';
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nunita';
|
||||
src: url('$lib/assets/fonts/Nunito-VariableFont_wght.ttf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
src: url('$lib/assets/fonts/Roboto-VariableFont_wdth,wght.ttf');
|
||||
}
|
||||
|
||||
:root {
|
||||
--theme-font-family-base: 'Roboto', serif;
|
||||
--theme-font-family-heading: 'Roboto', serif;
|
||||
}
|
||||
|
||||
:root body[data-theme='modern'],
|
||||
:root body[data-theme='gold-nouveau'] {
|
||||
--theme-font-family-base: 'Nunita', serif;
|
||||
--theme-font-family-heading: 'Nunita', serif;
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover" data-theme="vintage">
|
||||
<body data-sveltekit-preload-data="hover" data-theme="gold-nouveau">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
9
src/lib/components/About/Me.svelte
Normal file
9
src/lib/components/About/Me.svelte
Normal file
@ -0,0 +1,9 @@
|
||||
<script>
|
||||
import Header from "$lib/components/Common/Content/Heading.svelte";
|
||||
</script>
|
||||
|
||||
<div class="w-max h-1/2 m-auto flex flex-col">
|
||||
<Header content="Backwards Development"/>
|
||||
<p class="max-w-screen-lg">I'm Alexander Harding, I am the Founder of Backwards Development. I created Backwards Development as an umbrella for all of my professional works, this website was designed to allow for distribution for my software, tools and applications!</p>
|
||||
<p class="max-w-screen-lg">Backwards Development is a group I founded to work on whatever enter's my plate, If you need anything done, feel free to <a href="/#contact" class="text-primary-500 underline">Contact Us</a> at any time!</p>
|
||||
</div>
|
7
src/lib/components/About/Media.svelte
Normal file
7
src/lib/components/About/Media.svelte
Normal file
@ -0,0 +1,7 @@
|
||||
<script>
|
||||
import Heading from "$lib/components/Common/Content/Heading.svelte";
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Heading content="Backwards Media"/>
|
||||
</div>
|
5
src/lib/components/Common/Content/Heading.svelte
Normal file
5
src/lib/components/Common/Content/Heading.svelte
Normal file
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
export let content;
|
||||
</script>
|
||||
|
||||
<h1 class="h1 text-center pt-4">{content}</h1>
|
75
src/lib/components/Common/Tracker.svelte
Normal file
75
src/lib/components/Common/Tracker.svelte
Normal file
@ -0,0 +1,75 @@
|
||||
<script>
|
||||
import { sectionStore } from "$lib/stores/currentSection";
|
||||
import { onMount } from "svelte";
|
||||
import { fly, slide } from "svelte/transition";
|
||||
|
||||
export let page,
|
||||
slides,
|
||||
includeFirst = true;
|
||||
|
||||
let newSlides = includeFirst ? slides : slides.slice(1);
|
||||
|
||||
let pageSection = sectionStore[page];
|
||||
|
||||
let currentSection = $pageSection;
|
||||
|
||||
onMount(() => {
|
||||
pageSection.subscribe((cs) => {
|
||||
currentSection = cs;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if includeFirst ? currentSection >= 0 : currentSection > 0}
|
||||
<div
|
||||
in:fly={{ x: 50, duration: 300 }}
|
||||
out:fly={{ x: 50, duration: 300 }}
|
||||
class="tracker"
|
||||
>
|
||||
{#each newSlides as _, i}
|
||||
<div
|
||||
class="tracker-dot {(includeFirst ? i : i + 1) ===
|
||||
currentSection
|
||||
? 'active'
|
||||
: ''}"
|
||||
></div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
/* Tracker Styles */
|
||||
.tracker {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
right: 20px;
|
||||
transform: translateY(-50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tracker-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
@apply bg-surface-600;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.tracker-dot.active {
|
||||
@apply bg-primary-600;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
.tracker-dot {
|
||||
@apply bg-surface-300;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.tracker-dot.active {
|
||||
@apply bg-primary-600;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -3,9 +3,8 @@
|
||||
import MaterialSymbolsMail from '~icons/material-symbols/mail';
|
||||
</script>
|
||||
|
||||
|
||||
<div class="flex justify-center items-center">
|
||||
<form action="?/contact" class="w-full min-h-full dark:bg-surface-700 bg-surface-200 p-8 m-4 rounded-lg pr-12">
|
||||
<div class="w-screen h-screen flex justify-center items-center">
|
||||
<form action="?/contact" class="bg-surface-200 dark:bg-surface-900 w-1/2 h-max p-8 rounded-md">
|
||||
<h1 class="h1 font-bold ps-4 pb-4">Contact Us</h1>
|
||||
<hr class="opacity-25" />
|
||||
<p class="pt-4">Fullname</p>
|
||||
@ -30,9 +29,9 @@
|
||||
</select>
|
||||
</div>
|
||||
<p>Your Message</p>
|
||||
<textarea class="textarea mb-4" rows="4" placeholder="..." required ></textarea>
|
||||
<textarea class="textarea mb-4" rows="4" placeholder="What can we help you with?" required ></textarea>
|
||||
<div class="w-full text-end">
|
||||
<button type="submit" class="btn variant-filled-primary">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
104
src/lib/components/Main/Downloads.svelte
Normal file
104
src/lib/components/Main/Downloads.svelte
Normal file
@ -0,0 +1,104 @@
|
||||
<script>
|
||||
import { Avatar } from "@skeletonlabs/skeleton";
|
||||
import imageNotAvailable from '$lib/assets/Image_not_available.png';
|
||||
|
||||
// populate this with real data, using database?
|
||||
let Downloads = [
|
||||
{
|
||||
name: "DOT Bot Manager",
|
||||
description: "A Modular Discord bot to help you better manage your discord server the way *you* want.",
|
||||
author: {
|
||||
username: "BackwardsUser",
|
||||
icon: "https://cdn.discordapp.com/avatars/471172695862542337/306522a721ee716ba6348babfd9bbdff.webp?size=32"
|
||||
},
|
||||
date: "2025-01-13",
|
||||
thumbnail: "https://api.backwardsdevelopment.ca/images/treeline.jpg"
|
||||
},
|
||||
{
|
||||
name: "Mystic Helper Bot",
|
||||
description: "A bot that helps organize events, polls, and reminders with a magical twist!",
|
||||
author: {
|
||||
username: "MysticMaster",
|
||||
icon: "https://cdn.discordapp.com/avatars/123456789012345678/abc123def4567890abc123def4567890.webp?size=32"
|
||||
},
|
||||
date: "2025-01-12",
|
||||
thumbnail: "https://api.backwardsdevelopment.ca/images/treeline.jpg"
|
||||
},
|
||||
{
|
||||
name: "Game Stats Tracker",
|
||||
description: "Track your game stats and leaderboard rankings across various multiplayer games.",
|
||||
author: {
|
||||
username: "GameTrackerPro",
|
||||
icon: "https://cdn.discordapp.com/avatars/987654321098765432/def789abc123456789abc1234567890.webp?size=32"
|
||||
},
|
||||
date: "2025-01-11",
|
||||
thumbnail: "https://api.backwardsdevelopment.ca/images/treeline.jpg"
|
||||
},
|
||||
{
|
||||
name: "Quick Polls Bot",
|
||||
description: "Create and manage quick polls for your community to vote on different topics.",
|
||||
author: {
|
||||
username: "PollCreator",
|
||||
icon: "https://cdn.discordapp.com/avatars/112233445566778899/ghi345jkl9876543210ghi345jkl987654.webp?size=32"
|
||||
},
|
||||
date: "2025-01-10",
|
||||
thumbnail: "https://api.backwardsdevelopment.ca/images/treeline.jpg"
|
||||
},
|
||||
{
|
||||
name: "Music Party Bot",
|
||||
description: "Create your own music playlist and enjoy it with your friends in Discord voice channels.",
|
||||
author: {
|
||||
username: "DJPartyBot",
|
||||
icon: "https://cdn.discordapp.com/avatars/223344556677889900/jkl123mno4567890jkl123mno4567890.webp?size=32"
|
||||
},
|
||||
date: "2025-01-09",
|
||||
thumbnail: "https://example.com/images/music_party.jpg"
|
||||
}
|
||||
];
|
||||
|
||||
function imageAlt(event) {
|
||||
event.target.src = imageNotAvailable;
|
||||
event.target.classList.add("object-contain"); // Add object-contain for the alt image
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="w-screen min-h-screen">
|
||||
<h2 class="h2 text-center w-screen pt-4 font-nunito">Downloads</h2>
|
||||
<div class="px-32 py-16 grid grid-cols-2 md:grid-cols-3 gap-4">
|
||||
{#each Downloads as download}
|
||||
<a
|
||||
class="card variant-glass-surface card-hover overflow-hidden"
|
||||
href="/elements/cards"
|
||||
>
|
||||
<header>
|
||||
<!-- Main image (rectangle) -->
|
||||
<img
|
||||
src={download.thumbnail}
|
||||
class="bg-black/50 w-full aspect-[21/9] object-cover flex justify-center items-center"
|
||||
alt="Post"
|
||||
on:error={imageAlt}
|
||||
/>
|
||||
</header>
|
||||
<div class="p-4 space-y-4">
|
||||
<h3 class="h3" data-toc-ignore>{download.name}</h3>
|
||||
<article>
|
||||
<p>
|
||||
{download.description}
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
<hr class="opacity-50" />
|
||||
<footer class="p-4 flex justify-start items-center space-x-4">
|
||||
<Avatar
|
||||
src={download.author.icon}
|
||||
width="w-8"
|
||||
/>
|
||||
<div class="flex-auto flex justify-between items-center">
|
||||
<h6 class="font-bold" data-toc-ignore>By {download.author.username}</h6>
|
||||
<small>On {download.date}</small>
|
||||
</div>
|
||||
</footer>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
44
src/lib/components/Main/Header.svelte
Normal file
44
src/lib/components/Main/Header.svelte
Normal file
@ -0,0 +1,44 @@
|
||||
<script>
|
||||
import Hero from "$lib/components/Main/Hero.svelte";
|
||||
import ArrowDown from "~icons/material-symbols/keyboard-double-arrow-down-rounded";
|
||||
import { crossfade, fade, fly } from "svelte/transition";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
let isAtTop = true;
|
||||
|
||||
onMount(() => {
|
||||
const handleScroll = () => {
|
||||
isAtTop = window.scrollY === 0;
|
||||
};
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
return () => window.removeEventListener("scroll", handleScroll);
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Add these classes to your root container (likely in app.html or layout.svelte) -->
|
||||
<style>
|
||||
:global(html) {
|
||||
scroll-snap-type: y mandatory;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Add scroll-snap-align to your sections -->
|
||||
<header class="fancy-background align-center flex h-screen flex-col justify-between p-4 hero scroll-snap-start">
|
||||
<div class=""></div>
|
||||
<Hero></Hero>
|
||||
<div
|
||||
class="transition-all duration-300 text-xl self-center ease-in-out relative slide h-6"
|
||||
class:opacity-0={!isAtTop}
|
||||
>
|
||||
{#if isAtTop}
|
||||
<div
|
||||
class="animate-bounce"
|
||||
in:fly={{ x: 200, duration: 300 }}
|
||||
out:fly={{ x: -200, duration: 300 }}
|
||||
>
|
||||
<ArrowDown></ArrowDown>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</header>
|
8
src/lib/components/Main/Hero.svelte
Normal file
8
src/lib/components/Main/Hero.svelte
Normal file
@ -0,0 +1,8 @@
|
||||
<script>
|
||||
import BackwardsLogo from "$lib/assets/Backwards.png";
|
||||
</script>
|
||||
|
||||
<div class="text-center h-max self-center" id="hero">
|
||||
<h1 class="h1">Backwards Development</h1>
|
||||
<h4 class="h4">A Software Development and Distribution Company</h4>
|
||||
</div>
|
26
src/lib/components/Main/Media.svelte
Normal file
26
src/lib/components/Main/Media.svelte
Normal file
@ -0,0 +1,26 @@
|
||||
<script>
|
||||
import MaterialSymbolsArrowForwardRounded from "~icons/material-symbols/arrow-forward-rounded";
|
||||
import MaterialSymbolsLabProfileOutline from '~icons/material-symbols/lab-profile-outline';
|
||||
</script>
|
||||
|
||||
<div class="w-screen h-screen flex flex-col justify-center items-center">
|
||||
<h2 class="h2 font-bold">Backwards Media</h2>
|
||||
<h3 class="h3">Upload and Share Media with your Friends</h3>
|
||||
<div class="flex flex-row controls pt-4 gap-12">
|
||||
<a href="https://media.backwards.dev/" class="btn variant-filled-primary cool-hover">
|
||||
<span>Try it out</span>
|
||||
<span class="effect duration-500 ease-in-out rounded-xl"><MaterialSymbolsArrowForwardRounded /></span>
|
||||
</a>
|
||||
<a href="/about#media" class="btn variant-ghost-surface cool-hover">
|
||||
<span>Learn more</span>
|
||||
<span class="effect duration-500 ease-in-out rounded-xl"><MaterialSymbolsLabProfileOutline /></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* dumb ass name :(, cool ass animation :) */
|
||||
.cool-hover:hover>.effect {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
</style>
|
18
src/lib/components/Main/TechStack.svelte
Normal file
18
src/lib/components/Main/TechStack.svelte
Normal file
@ -0,0 +1,18 @@
|
||||
<script>
|
||||
import Techs from '$lib/data/techstack.json';
|
||||
import { Avatar } from '@skeletonlabs/skeleton';
|
||||
</script>
|
||||
|
||||
<div class="w-screen h-screen flex flex-col justify-center items-center">
|
||||
<h2 class="h2 font-bold pb-0">Our Preferred Tech Stack</h2>
|
||||
<span class="text-sm pt-0 pb-4 text-surface-200">Subject to change</span>
|
||||
<div class="w-1/2 flex flex-wrap gap-4 justify-center">
|
||||
{#each Techs as tech}
|
||||
<a href={tech.url} class="min-w-72 flex flex-row justify-between items-center card card-hover p-4 hover:bg-surface-700 rounded-lg">
|
||||
<Avatar class="p-2" src={tech.logo} alt={`Logo of ${tech.name}`} />
|
||||
<span class="text-xl">{tech.name}</span>
|
||||
<div class="spacer"></div>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
@ -1,27 +0,0 @@
|
||||
<script>
|
||||
import BrandIcon from "$lib/components/items/BrandIcon.svelte";
|
||||
|
||||
export let brands;
|
||||
</script>
|
||||
|
||||
<header class="w-full h-screen flex flex-col justify-center items-center">
|
||||
<div id="header-wrapper" class="header-wrapper text-center">
|
||||
<h1 id="title" class="h1">Alexander Harding</h1>
|
||||
<h4 class="h4 m-0">Software and Application Developer</h4>
|
||||
<div class="cards flex w-full justify-between mt-6">
|
||||
{#each brands as brand}
|
||||
<BrandIcon url={brand.url} icon={brand.icon} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
.header-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#title.fixed {
|
||||
transform: translateY(-100%) translateX(-0.75em);
|
||||
}
|
||||
</style>
|
@ -1,19 +0,0 @@
|
||||
<script>
|
||||
import LargeCard from "../items/LargeCard.svelte";
|
||||
|
||||
import projects from "$lib/data/projects.json";
|
||||
import LargeCardSm from "../items/LargeCard-sm.svelte";
|
||||
|
||||
export let data;
|
||||
|
||||
const { avatars } = data;
|
||||
</script>
|
||||
|
||||
<div id="projects" class="h-full">
|
||||
<h2 class="h2 mb-4">Projects</h2>
|
||||
<div class="h-fit gap-4 flex flex-col overflow-scroll">
|
||||
{#each projects as project}
|
||||
<LargeCardSm data={project} {avatars} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
@ -1,12 +0,0 @@
|
||||
<script>
|
||||
import SmallCard from "../items/SmallCard.svelte";
|
||||
|
||||
export let techs;
|
||||
</script>
|
||||
|
||||
<h2 class="h2">My Tech Stack</h2>
|
||||
<div class="cards">
|
||||
{#each techs as tech}
|
||||
<SmallCard data={tech} />
|
||||
{/each}
|
||||
</div>
|
@ -1,7 +0,0 @@
|
||||
<script>
|
||||
export let url, icon, redirect;
|
||||
</script>
|
||||
|
||||
<a href={url} target={ redirect = true ? "_blank" : "" } class="btn variant-filled-surface text-2xl p-3 rounded-md spin">
|
||||
<span class="block spinner duration-500"><svelte:component this={icon}></svelte:component></span>
|
||||
</a>
|
@ -1,39 +0,0 @@
|
||||
<script>
|
||||
import { Avatar } from "@skeletonlabs/skeleton";
|
||||
|
||||
const fallbackThumbnail = "/Image_not_available.png";
|
||||
const fallbackAvatar = "/default.png";
|
||||
|
||||
function handleImageError(event) {
|
||||
event.target.src = fallbackThumbnail;
|
||||
}
|
||||
|
||||
export let data, avatars;
|
||||
|
||||
const avatar = avatars[data.author.username];
|
||||
</script>
|
||||
|
||||
<a href={data.url} class="card variant-glass-surface card-hover overflow-hidden flex flex-col w-64">
|
||||
<img
|
||||
src={data.thumbnail || fallbackThumbnail}
|
||||
class="bg-black/50 aspect-[21/9] object-cover"
|
||||
alt={data.name}
|
||||
loading="lazy"
|
||||
on:error={handleImageError}
|
||||
/>
|
||||
|
||||
<div class="p-3 space-y-2 flex-auto">
|
||||
<h3 class="text-lg font-bold truncate">{data.name}</h3>
|
||||
<p class="text-sm line-clamp-2">{data.description}</p>
|
||||
</div>
|
||||
|
||||
<hr class="opacity-50 mx-3" />
|
||||
|
||||
<footer class="p-3 flex items-center space-x-3 text-xs">
|
||||
<Avatar src={avatar || fallbackAvatar} width="w-6" />
|
||||
<div class="flex-auto truncate">
|
||||
<h6 class="font-semibold">By {data.author.username}</h6>
|
||||
<small class="opacity-75">Updated {data.date}</small>
|
||||
</div>
|
||||
</footer>
|
||||
</a>
|
@ -1,43 +0,0 @@
|
||||
<script>
|
||||
import { Avatar } from "@skeletonlabs/skeleton";
|
||||
|
||||
const fallbackThumbnail = "/Image_not_available.png";
|
||||
const fallbackAvatar = "/default.png";
|
||||
|
||||
function handleImageError(event) {
|
||||
event.target.src = fallbackThumbnail;
|
||||
}
|
||||
|
||||
export let data, avatars;
|
||||
|
||||
const avatar = avatars[data.author.username];
|
||||
</script>
|
||||
|
||||
<a href={data.url} class="card w-min variant-glass-surface card-hover overflow-hidden flex flex-col">
|
||||
<header>
|
||||
<img
|
||||
src={data.thumbnail || fallbackThumbnail}
|
||||
class="bg-black/50 aspect=[21/9] object-cover flex justify-center items-center"
|
||||
alt={data.name}
|
||||
loading="lazy"
|
||||
on:error={handleImageError}>
|
||||
</header>
|
||||
<div class="p-4 space-y-4 flex-auto">
|
||||
<h3 class="h3" data-toc-ignore>{data.name}</h3>
|
||||
<article>
|
||||
<p>
|
||||
{data.description}
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
<hr class="opacity-50" />
|
||||
<footer class="p-4 flex text-nowrap justify-start items-center space-x-4">
|
||||
<Avatar src={avatar || fallbackAvatar} width="w-8" />
|
||||
<div class="flex-auto gap-6 flex justify-between items-center">
|
||||
<h6 class="font-bold" data-toc-ignore>
|
||||
By {data.author.username}
|
||||
</h6>
|
||||
<small>Updated {data.date}</small>
|
||||
</div>
|
||||
</footer>
|
||||
</a>
|
@ -1,11 +0,0 @@
|
||||
<script>
|
||||
import { Avatar } from "@skeletonlabs/skeleton";
|
||||
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<a href="{data.url}" class="m-4 flex flex-row justify-between items-center card card-hover p-4 dark:hover:bg-surface-700 hover:bg-surface-200 rounded-lg">
|
||||
<Avatar class="p-2" src={data.logo} alt={`Logo of ${data.name}`} />
|
||||
<span class="text-xl">{data.name}</span>
|
||||
<div class="spacer"></div>
|
||||
</a>
|
@ -1,117 +0,0 @@
|
||||
<script>
|
||||
import MdiGithub from "~icons/mdi/github";
|
||||
import MdiYoutube from "~icons/mdi/youtube";
|
||||
import MdiDiscord from "~icons/mdi/discord";
|
||||
import MdiLinkedin from "~icons/mdi/linkedin";
|
||||
import MdiResume from '~icons/mdi/resume';
|
||||
import CibGitea from "~icons/cib/gitea";
|
||||
import MaterialSymbolsPerson from '~icons/material-symbols/person';
|
||||
import MaterialSymbolsMail from '~icons/material-symbols/mail';
|
||||
import MaterialSymbolsCalendarClockOutline from '~icons/material-symbols/calendar-clock-outline';
|
||||
|
||||
|
||||
import Header from "$lib/components/cards/Header.svelte";
|
||||
import SmallCard from "../items/SmallCard.svelte";
|
||||
|
||||
import techs from "$lib/data/techstack.json";
|
||||
import projects from "$lib/data/projects.json";
|
||||
|
||||
import { onMount } from "svelte";
|
||||
import DylanIpsum from "dylan-ipsum";
|
||||
import LargeCard from "../items/LargeCard.svelte";
|
||||
import Contact from "../containers/Contact.svelte";
|
||||
|
||||
export let data;
|
||||
|
||||
const brands = [
|
||||
{ url: "https://www.github.com/BackwardsUser", icon: MdiGithub },
|
||||
{ url: "https://git.backwards.dev/", icon: CibGitea },
|
||||
{ url: "https://api.backwards.dev/files/Alexander_Harding_Resume.docx", icon: MdiResume },
|
||||
{ url: "https://www.linkedin.com/in/alexander-harding-71b661265/", icon: MdiLinkedin },
|
||||
{ url: "https://doodle.com/bp/backwards_user__/schedule-a-meeting", icon: MaterialSymbolsCalendarClockOutline },
|
||||
{ url: "https://discord.gg/Zhq9yjhHKr", icon: MdiDiscord },
|
||||
{ url: "https://www.youtube.com/@BackwardsDevelopment", icon: MdiYoutube },
|
||||
];
|
||||
|
||||
const downloads = [];
|
||||
|
||||
let End = 300;
|
||||
let rightStart = 0;
|
||||
|
||||
function setSidebars() {
|
||||
let rPos = Math.min(window.scrollY / End, 1);
|
||||
let lPos = Math.min(Math.max((window.scrollY - rightStart) / End, 0), 1);
|
||||
document.getElementById("left").style =
|
||||
`transform: translateX(${(lPos - 1) * 100}%);`;
|
||||
document.getElementById("right").style =
|
||||
`transform: translateX(${Math.abs(rPos - 1) * 100}%);`;
|
||||
}
|
||||
|
||||
const avatars = data.avatars;
|
||||
|
||||
onMount(() => {
|
||||
setSidebars();
|
||||
window.addEventListener("scroll", setSidebars);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="main" class="w-screen grid">
|
||||
<div id="left" class="sidebar h-screen bg-surface-200 dark:bg-surface-500 text-center">
|
||||
<h4 class="h4">My Tech Stack</h4>
|
||||
<div class="cards">
|
||||
{#each techs as tech}
|
||||
<SmallCard data={tech} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<Header {brands}></Header>
|
||||
<div id="projects" class="flex py-8 m-4 flex-col justify-center items-center bg-surface-200 dark:bg-surface-500 rounded-lg">
|
||||
<h1 class="h1 pb-8">Projects</h1>
|
||||
<div class="flex flex-shrink-0 flex-wrap justify-center gap-4">
|
||||
{#each projects as project}
|
||||
<LargeCard data={project} {avatars} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<div id="contact">
|
||||
<Contact />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="right" class="sidebar h-screen bg-surface-200 dark:bg-surface-500 text-center">
|
||||
<h4 class="h4">Downloads</h4>
|
||||
{#if downloads.length > 0}
|
||||
{#each downloads as download}
|
||||
<p class="pt-4">-- Not Implemented --</p>
|
||||
{/each}
|
||||
{:else}
|
||||
<p class="pt-4">-- No files uploaded --</p>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#main {
|
||||
contain: paint;
|
||||
grid-template-columns: 20% 60% 20%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#left {
|
||||
border-radius: 0 0.5em 0.5em 0;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
#right {
|
||||
border-radius: 0.5em 0 0 0.5em;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
@ -1,51 +0,0 @@
|
||||
<script>
|
||||
import MdiGithub from "~icons/mdi/github";
|
||||
import MdiYoutube from "~icons/mdi/youtube";
|
||||
import MdiDiscord from "~icons/mdi/discord";
|
||||
import MdiLinkedin from "~icons/mdi/linkedin";
|
||||
import MdiResume from '~icons/mdi/resume';
|
||||
import CibGitea from "~icons/cib/gitea";
|
||||
import MaterialSymbolsPerson from '~icons/material-symbols/person';
|
||||
import MaterialSymbolsMail from '~icons/material-symbols/mail';
|
||||
import MaterialSymbolsCalendarClockOutline from '~icons/material-symbols/calendar-clock-outline';
|
||||
|
||||
import Header from "../cards/Header.svelte";
|
||||
import Projects from "../containers/Projects.svelte";
|
||||
import TechStack from "../containers/TechStack.svelte";
|
||||
|
||||
import techs from "$lib/data/techstack.json";
|
||||
|
||||
export let data;
|
||||
|
||||
const brands = [
|
||||
{ url: "https://www.github.com/BackwardsUser", icon: MdiGithub, redirect: false },
|
||||
{ url: "https://git.backwards.dev/", icon: CibGitea, redirect: false },
|
||||
{ url: "https://api.backwards.dev/files/Alexander_Harding_Resume.docx", icon: MdiResume, redirect: false },
|
||||
{ url: "https://www.linkedin.com/in/alexander-harding-71b661265/", icon: MdiLinkedin, redirect: false },
|
||||
{ url: "https://doodle.com/bp/backwards_user__/schedule-a-meeting", icon: MaterialSymbolsCalendarClockOutline, redirect: true },
|
||||
{ url: "https://discord.gg/Zhq9yjhHKr", icon: MdiDiscord, redirect: false },
|
||||
{ url: "https://www.youtube.com/@BackwardsDevelopment", icon: MdiYoutube, redirect: false },
|
||||
];
|
||||
</script>
|
||||
|
||||
<Header {brands} />
|
||||
|
||||
<!-- <div class="main flex flex-col gap-8">
|
||||
<div class="section">
|
||||
<Header {brands} />
|
||||
</div>
|
||||
<div class="section bg-surface-800 py-4 rounded-2xl flex flex-col">
|
||||
<TechStack {techs} />
|
||||
</div>
|
||||
<div class="section bg-surface-800 py-4 rounded-2xl">
|
||||
<Projects {data} />
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<style>
|
||||
.section {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
@ -1,35 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "PlugsyCord",
|
||||
"description": "A Modular Discord bot to help you better manage your discord server the way *you* want.",
|
||||
"author": {
|
||||
"username": "BackwardsUser",
|
||||
"icon": "https://cdn.discordapp.com/avatars/471172695862542337/306522a721ee716ba6348babfd9bbdff.webp?size=32"
|
||||
},
|
||||
"date": "22/02/2025",
|
||||
"url": "https://github.com/BackwardsUser/PlugsyCord",
|
||||
"thumbnail": "https://api.backwardsdevelopment.ca/images/PlugsyCord-exbanner.png"
|
||||
},
|
||||
{
|
||||
"name": "HTTP Proxy",
|
||||
"description": "A HTTP Proxy tool that allows for incoming traffic to be routed to a given url.",
|
||||
"author": {
|
||||
"username": "BackwardsUser",
|
||||
"icon": "https://cdn.discordapp.com/avatars/471172695862542337/306522a721ee716ba6348babfd9bbdff.webp?size=32"
|
||||
},
|
||||
"date": "00/00/0000",
|
||||
"url": "https://github.com/BackwardsUser/http-proxy",
|
||||
"thumbnail": null
|
||||
},
|
||||
{
|
||||
"name": "My API",
|
||||
"description": "A dynamic content hub for hosting scripts, media, files, and themes, powered by a custom file explorer.",
|
||||
"author": {
|
||||
"username": "BackwardsUser",
|
||||
"icon":"https://cdn.discordapp.com/avatars/471172695862542337/306522a721ee716ba6348babfd9bbdff.webp?size=32"
|
||||
},
|
||||
"date": "02/10/2024",
|
||||
"url": "https://api.backwards.dev/patchnotes_latest.txt",
|
||||
"thumbnail": null
|
||||
}
|
||||
]
|
@ -6,7 +6,7 @@
|
||||
},
|
||||
{
|
||||
"name": "Tailwindcss",
|
||||
"logo": "https://tailwindcss.com/_next/static/media/tailwindcss-mark.d52e9897.svg",
|
||||
"logo": "https://tailwindcss.com/_next/static/media/tailwindcss-mark.3c5441fc7a190fb1800d4a5c7f07ba4b1345a9c8.svg",
|
||||
"url": "https://tailwindcss.com/"
|
||||
},
|
||||
{
|
||||
|
6
src/lib/stores/currentSection.js
Normal file
6
src/lib/stores/currentSection.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
export let sectionStore = {
|
||||
about: writable(),
|
||||
main: writable()
|
||||
};
|
@ -2,12 +2,6 @@
|
||||
import '../app.css';
|
||||
import { autoModeWatcher } from '@skeletonlabs/skeleton';
|
||||
|
||||
import "@fontsource/abril-fatface";
|
||||
import "@fontsource/inter";
|
||||
import "@fontsource/playfair-display";
|
||||
import "@fontsource/quicksand";
|
||||
import "@fontsource/space-grotesk";
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
import axios from "axios"
|
||||
import { DISCORD_TOKEN } from "$env/static/private"
|
||||
|
||||
export const load = async () => {
|
||||
let content;
|
||||
try {
|
||||
content = await axios.get("https://discord.com/api/v9/users/@me", {
|
||||
headers: {
|
||||
"Authorization": DISCORD_TOKEN
|
||||
}
|
||||
});
|
||||
} catch {
|
||||
return {
|
||||
avatars: {
|
||||
"BackwardsUser": "/default.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
avatars: {
|
||||
"BackwardsUser": `https://cdn.discordapp.com/avatars/${content.data.id}/${content.data.avatar}.png?size=64`
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +1,85 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import Large from "$lib/components/pages/Large.svelte";
|
||||
import Small from "$lib/components/pages/Small.svelte";
|
||||
import { onMount } from "svelte";
|
||||
import Header from "$lib/components/Main/Header.svelte";
|
||||
import Downloads from "$lib/components/Main/Downloads.svelte";
|
||||
import { fly, slide } from "svelte/transition";
|
||||
import Media from "$lib/components/Main/Media.svelte";
|
||||
import Contact from "$lib/components/Main/Contact.svelte";
|
||||
import TechStack from "$lib/components/Main/TechStack.svelte";
|
||||
import Tracker from "$lib/components/Common/Tracker.svelte";
|
||||
import { sectionStore } from "$lib/stores/currentSection";
|
||||
|
||||
export let data;
|
||||
/* IMPORTANT */
|
||||
// Anything added into the page directly will likely break the page's scrolling behaviour
|
||||
// To properly add something to the main page, make it into a component and add it to the array.
|
||||
// This array is in order of how they are to be displayed, modifying their positions will modify them in page.
|
||||
|
||||
let width = 0;
|
||||
let slides = [Header, Downloads, Media, TechStack, Contact];
|
||||
|
||||
onMount(() => {
|
||||
const updateWidth = () => {
|
||||
width = window.innerWidth;
|
||||
let { main } = sectionStore;
|
||||
|
||||
if (!$main) main.set(0);
|
||||
|
||||
let currentSection = $main;
|
||||
|
||||
// Update the current section based on scroll position
|
||||
const handleScroll = () => {
|
||||
const sections = document.querySelectorAll(".section");
|
||||
const scrollTop = document.querySelector(".scroll-container").scrollTop;
|
||||
sections.forEach((section, index) => {
|
||||
if (section.offsetTop <= scrollTop + window.innerHeight / 2) {
|
||||
main.set(index);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
updateWidth(); // Set initial width
|
||||
window.addEventListener("resize", updateWidth);
|
||||
|
||||
return () => window.removeEventListener("resize", updateWidth);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="page-wrapper">
|
||||
{#if width >= 768}
|
||||
<Large {data} />
|
||||
{:else}
|
||||
<Small {data} />
|
||||
{/if}
|
||||
<div id="main" class="scroll-container" on:scroll={handleScroll}>
|
||||
{#each slides as content}
|
||||
<section class="section">
|
||||
<svelte:component this={content} />
|
||||
</section>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<!-- Tracker -->
|
||||
<Tracker page="main" {slides} includeFirst={false} />
|
||||
|
||||
<style>
|
||||
.scroll-container {
|
||||
scroll-snap-type: y mandatory;
|
||||
overflow-y: auto;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.section {
|
||||
scroll-snap-align: start;
|
||||
min-height: 100vh; /* Full viewport height */
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
/* Tracker Styles */
|
||||
.tracker {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
right: 20px;
|
||||
transform: translateY(-50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tracker-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
@apply bg-surface-600;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.tracker-dot.active {
|
||||
@apply bg-primary-600;
|
||||
}
|
||||
</style>
|
||||
|
61
src/routes/about/+page.svelte
Normal file
61
src/routes/about/+page.svelte
Normal file
@ -0,0 +1,61 @@
|
||||
<script>
|
||||
import Me from '$lib/components/About/Me.svelte';
|
||||
import Media from '$lib/components/About/Media.svelte';
|
||||
import Tracker from '$lib/components/Common/Tracker.svelte';
|
||||
import { sectionStore } from '$lib/stores/currentSection';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
/* IMPORTANT */
|
||||
// Anything added into the page directly will likely break the page's scrolling behaviour
|
||||
// To properly add something to the main page, make it into a component and add it to the array.
|
||||
// This array is in order of how they are to be displayed, modifying their positions will modify them in page.
|
||||
|
||||
let slides = [
|
||||
Me,
|
||||
Media
|
||||
];
|
||||
|
||||
let { about } = sectionStore
|
||||
|
||||
if (!$about) about.set(0);
|
||||
|
||||
let currentSection = $about;
|
||||
|
||||
// Update the current section based on scroll position
|
||||
const handleScroll = () => {
|
||||
const sections = document.querySelectorAll('.section');
|
||||
const scrollTop = document.querySelector('.scroll-container').scrollTop;
|
||||
sections.forEach((section, index) => {
|
||||
if (section.offsetTop <= scrollTop + window.innerHeight / 2) {
|
||||
about.set(index);
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<div id="main" class="scroll-container" on:scroll={handleScroll}>
|
||||
{#each slides as content}
|
||||
<section class="section flex flex-row">
|
||||
<svelte:component this={content} />
|
||||
</section>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<!-- Tracker -->
|
||||
<Tracker page="about" slides={slides} />
|
||||
|
||||
<style>
|
||||
.scroll-container {
|
||||
scroll-snap-type: y mandatory;
|
||||
overflow-y: auto;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.section {
|
||||
scroll-snap-align: start;
|
||||
min-height: 100vh; /* Full viewport height */
|
||||
width: 100vw;
|
||||
}
|
||||
</style>
|
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
@ -18,18 +18,7 @@ export default {
|
||||
plugins: [
|
||||
forms,
|
||||
skeleton({
|
||||
themes: { preset: [
|
||||
{ name: "skeleton", enhancements: true },
|
||||
{ name: "wintry", enhancements: true },
|
||||
{ name: "modern", enhancements: true },
|
||||
{ name: "rocket", enhancements: true },
|
||||
{ name: "seafoam", enhancements: true },
|
||||
{ name: "vintage", enhancements: true },
|
||||
{ name: "sahara", enhancements: true },
|
||||
{ name: "hamlindigo", enhancements: true },
|
||||
{ name: "gold-nouveau", enhancements: true },
|
||||
{ name: "crimson", enhancements: true }
|
||||
]}
|
||||
themes: { preset: [ "skeleton", "wintry", "modern", "rocket", "seafoam", "vintage", "sahara", "hamlindigo", "gold-nouveau", "crimson" ]}
|
||||
})
|
||||
]
|
||||
}
|
@ -9,8 +9,5 @@ export default defineConfig({
|
||||
compiler: 'svelte',
|
||||
autoInstall: true
|
||||
})
|
||||
],
|
||||
build: {
|
||||
outDir: '../../build'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
@ -1,17 +0,0 @@
|
||||
// vite.config.js
|
||||
import { sveltekit } from "file:///C:/Users/alexa/Documents/Coding/NodeJS/Webpages/backwards.dev/node_modules/@sveltejs/kit/src/exports/vite/index.js";
|
||||
import { defineConfig } from "file:///C:/Users/alexa/Documents/Coding/NodeJS/Webpages/backwards.dev/node_modules/vite/dist/node/index.js";
|
||||
import Icons from "file:///C:/Users/alexa/Documents/Coding/NodeJS/Webpages/backwards.dev/node_modules/unplugin-icons/dist/vite.js";
|
||||
var vite_config_default = defineConfig({
|
||||
plugins: [
|
||||
sveltekit(),
|
||||
Icons({
|
||||
compiler: "svelte",
|
||||
autoInstall: true
|
||||
})
|
||||
]
|
||||
});
|
||||
export {
|
||||
vite_config_default as default
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFxhbGV4YVxcXFxEb2N1bWVudHNcXFxcQ29kaW5nXFxcXE5vZGVKU1xcXFxXZWJwYWdlc1xcXFxiYWNrd2FyZHMuZGV2XCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFxhbGV4YVxcXFxEb2N1bWVudHNcXFxcQ29kaW5nXFxcXE5vZGVKU1xcXFxXZWJwYWdlc1xcXFxiYWNrd2FyZHMuZGV2XFxcXHZpdGUuY29uZmlnLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9DOi9Vc2Vycy9hbGV4YS9Eb2N1bWVudHMvQ29kaW5nL05vZGVKUy9XZWJwYWdlcy9iYWNrd2FyZHMuZGV2L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgc3ZlbHRla2l0IH0gZnJvbSAnQHN2ZWx0ZWpzL2tpdC92aXRlJztcclxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSc7XHJcbmltcG9ydCBJY29ucyBmcm9tICd1bnBsdWdpbi1pY29ucy92aXRlJ1xyXG5cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuXHRwbHVnaW5zOiBbXHJcblx0XHRzdmVsdGVraXQoKSxcclxuXHRcdEljb25zKHtcclxuXHRcdFx0Y29tcGlsZXI6ICdzdmVsdGUnLFxyXG5cdFx0XHRhdXRvSW5zdGFsbDogdHJ1ZVxyXG5cdFx0fSlcclxuXHRdXHJcbn0pO1xyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXlYLFNBQVMsaUJBQWlCO0FBQ25aLFNBQVMsb0JBQW9CO0FBQzdCLE9BQU8sV0FBVztBQUVsQixJQUFPLHNCQUFRLGFBQWE7QUFBQSxFQUMzQixTQUFTO0FBQUEsSUFDUixVQUFVO0FBQUEsSUFDVixNQUFNO0FBQUEsTUFDTCxVQUFVO0FBQUEsTUFDVixhQUFhO0FBQUEsSUFDZCxDQUFDO0FBQUEsRUFDRjtBQUNELENBQUM7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
Loading…
x
Reference in New Issue
Block a user