Compare commits

...

No commits in common. "main" and "gh-pages" have entirely different histories.

42 changed files with 73 additions and 20972 deletions

View File

@ -1,4 +0,0 @@
// TODO: Follow https://www.tommyp.org/blog/adding-spotify-now-playing-to-astro and remove this comment
CLIENT_ID=
CLIENT_SECRET=
REFRESH_TOKEN=

View File

@ -1,24 +0,0 @@
name: Deploy site to GitHub Pages
on:
push:
branches:
- main
permissions:
contents: write # ✅ allow pushing to branches
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '22'
- run: npm install
- run: npm run build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist

138
.gitignore vendored
View File

@ -1,138 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Astro
.astro
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
.output
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for (testing) VSCode extensions
.vscode
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# Netlify
.netlify

0
.nojekyll Normal file
View File

View File

@ -1,44 +0,0 @@
# Dependency directories
node_modules/
dist/
build/
out/
# Lock files
pnpm-lock.yaml
package-lock.json
yarn.lock
# Build and generated files
*.min.*
*.bundle.*
*.map
# Git and version control
**/.git
# Framework-specific files
next-env.d.ts
__generated__/
# Test and coverage files
coverage/
*.spec.*
*.test.*
# Editor-specific files
.vscode/
.idea/
*.sublime-project
*.sublime-workspace
# OS generated files
.DS_Store
Thumbs.db
# Markdown and MDX files
*.md
*.mdx
# Changelog
.changeset

View File

@ -1,29 +0,0 @@
{
"plugins": ["prettier-plugin-astro", "@trivago/prettier-plugin-sort-imports"],
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": false,
"endOfLine": "lf",
"htmlWhitespaceSensitivity": "css",
"overrides": [
{
"files": "*.astro",
"options": {
"parser": "astro"
}
}
],
"importOrder": [
"<THIRD_PARTY_MODULES>",
"^@internal/(.*)$",
"^@/models/(.*)$",
"^@/utils/(.*)$",
"^@/components/(?!ui/)(.*)$",
"^@/components/ui/(.*)$",
"^[./].*(?<!\\.(c|le|sc)ss)$",
"^[.]/[-a-zA-Z0-9_]+[.](module)[.](css|scss|less)$"
],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true
}

1
CNAME Normal file
View File

@ -0,0 +1 @@
kremta.dev

22
LICENSE
View File

@ -1,22 +0,0 @@
MIT License
Copyright (c) 2025 Kristian Emil Takvam
Copyright (c) 2024-present, trueberryless
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,13 +0,0 @@
<div align="center">
<img src="src/assets/banner.png" style="width:80%;" alt="banner" align="center" />
</div>
---
[![GitHub License](https://img.shields.io/github/license/astrogon/astrogon?color=red)](https://github.com/Kremtastic/Kremtastic.github.io/blob/main/LICENSE) [![Repo Size](https://img.shields.io/github/repo-size/kremtastic/Kremtastic.github.io)](https://github.com/Kremtastic/Kremtastic.github.io) ![GitHub branch check runs](https://img.shields.io/github/check-runs/kremtastic/Kremtastic.github.io/main) [![Website](https://img.shields.io/website?up_message=online&up_color=limegreen&down_message=offline&down_color=yellow&url=https%3A%2F%2Fastrogon.reednel.com%2F)](https://kremtastic.github.io/)
Heres the repo for my personal website!
---
###### *Built with the <a href="https://github.com/trueberryless-org/astro-portfolio-template" target="_blank">Astro-portfolio-template</a> theme by <a href="https://trueberryless.org/" target="_blank">@trueberryless</a> (MIT License)*

View File

@ -0,0 +1,18 @@
import{r as c}from"./index.Cd_vQiNd.js";var h={exports:{}},x={};/**
* @license React
* react-jsx-runtime.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var v;function m(){if(v)return x;v=1;var r=Symbol.for("react.transitional.element"),a=Symbol.for("react.fragment");function u(d,n,t){var s=null;if(t!==void 0&&(s=""+t),n.key!==void 0&&(s=""+n.key),"key"in n){t={};for(var l in n)l!=="key"&&(t[l]=n[l])}else t=n;return n=t.ref,{$$typeof:r,type:d,key:s,ref:n!==void 0?n:null,props:t}}return x.Fragment=a,x.jsx=u,x.jsxs=u,x}var g;function y(){return g||(g=1,h.exports=m()),h.exports}var e=y();const j=({progress:r,isPlaying:a})=>{const[u,d]=c.useState([]);c.useEffect(()=>{const t=[];for(let s=0;s<50;s++)t.push(Math.floor(Math.random()*800)+700);d(t)},[]);const n=()=>{const t=Math.floor(r/2),s=[],l=a?3:8,i=a?25:20;for(let o=1;o<51;o++){const p=o<=t;s.push(e.jsx("line",{x1:o+o*6,y1:l,x2:o+o*6,y2:i,strokeWidth:"2",stroke:p?"var(--ctp-green)":"var(--ctp-overlay0)",style:{transformOrigin:"center",transition:"stroke 1s ease-in-out",animation:a?`sound ${u[o]}ms linear infinite alternate`:"none"}},o))}return s};return e.jsxs("div",{children:[e.jsx("svg",{width:"302",height:"28",viewBox:"0 0 344 28",fill:"none",xmlns:"http://www.w3.org/2000/svg",style:{maxWidth:"100%",height:"auto"},children:n()}),e.jsx("style",{children:`
@keyframes sound {
0% {
transform: scaleY(0.4);
}
100% {
transform: scaleY(1);
}
}
`})]})},k=()=>{const[r,a]=c.useState(null),[u,d]=c.useState(!1),[n,t]=c.useState(!0),[s,l]=c.useState(0);return c.useEffect(()=>{const i=async()=>{try{const p=await fetch("/api/spotify/now-playing");if(p.status===204){a(null),d(!1),t(!1);return}const f=await p.json();a(f),d(f.isPlaying),l(f.progress||0),t(!1)}catch(p){console.error("Error fetching now playing:",p),t(!1)}};i();const o=setInterval(i,1e4);return()=>clearInterval(o)},[]),n?e.jsx("div",{style:{textAlign:"center",color:"var(--ctp-subtext0)"},children:"Loading..."}):r?e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"1.5rem"},children:[e.jsxs("div",{style:{display:"flex",gap:"1.5rem",alignItems:"center"},children:[r.albumArt&&e.jsx("img",{src:r.albumArt,alt:r.album,style:{width:"80px",height:"80px",borderRadius:"8px",border:"2px solid var(--ctp-green)"}}),e.jsxs("div",{style:{flex:1,minWidth:0},children:[e.jsx("div",{style:{fontSize:"1.25rem",fontWeight:"600",color:"var(--ctp-text)",marginBottom:"0.25rem",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:r.title}),e.jsx("div",{style:{fontSize:"1rem",color:"var(--ctp-subtext0)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:r.artist}),r.album&&e.jsx("div",{style:{fontSize:"0.9rem",color:"var(--ctp-subtext1)",marginTop:"0.25rem",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:r.album})]})]}),e.jsx("div",{style:{display:"flex",justifyContent:"center"},children:e.jsx(j,{progress:s,isPlaying:u})}),r.trackUrl&&e.jsx("a",{href:r.trackUrl,target:"_blank",rel:"noopener noreferrer",style:{display:"inline-flex",alignItems:"center",gap:"0.5rem",padding:"0.75rem 1.5rem",backgroundColor:"var(--ctp-green)",color:"var(--ctp-base)",borderRadius:"9999px",textDecoration:"none",fontWeight:"500",alignSelf:"center",transition:"all 0.3s ease"},onMouseEnter:i=>{i.currentTarget.style.transform="scale(1.05)",i.currentTarget.style.backgroundColor="var(--ctp-teal)"},onMouseLeave:i=>{i.currentTarget.style.transform="scale(1)",i.currentTarget.style.backgroundColor="var(--ctp-green)"},children:"Open in Spotify"})]}):e.jsxs("div",{style:{textAlign:"center",color:"var(--ctp-subtext0)"},children:[e.jsx("svg",{width:"64",height:"64",viewBox:"0 0 24 24",fill:"none",style:{margin:"0 auto 1rem",color:"var(--ctp-green)"},children:e.jsx("path",{d:"M9 18V5l12-2v13M9 18c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3zm12-2c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})}),e.jsx("p",{children:"Not playing anything right now"})]})};export{k as default};

33
_astro/client.BfPWZUkF.js Normal file

File diff suppressed because one or more lines are too long

9
_astro/index.Cd_vQiNd.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.project[data-astro-cid-amng4zvp]{padding:6rem 2rem;display:flex;justify-content:center}.content[data-astro-cid-amng4zvp]{max-width:600px;width:100%}.section-title[data-astro-cid-amng4zvp]{font-size:2rem;font-weight:600;color:var(--ctp-text);margin-bottom:3rem;text-align:center}.projects[data-astro-cid-amng4zvp]{display:flex;flex-direction:column;gap:1.5rem}.project-link[data-astro-cid-amng4zvp]{display:flex;align-items:center;gap:1rem;padding:1.5rem 2rem;background-color:var(--ctp-surface0);border:2px solid var(--project-color);border-radius:12px;text-decoration:none;color:var(--ctp-text);transition:all .3s ease;position:relative;overflow:hidden}.project-link[data-astro-cid-amng4zvp]:before{content:"";position:absolute;inset:-1px;background-color:var(--project-color);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.4,0,.2,1);z-index:0}.project-link[data-astro-cid-amng4zvp]:hover:before{transform:scaleX(1)}.project-icon[data-astro-cid-amng4zvp]{font-size:1.5rem;color:var(--project-color);transition:all .3s ease;z-index:1}.project-name[data-astro-cid-amng4zvp]{flex:1;font-size:1.25rem;font-weight:500;z-index:1;transition:color .3s ease}.project-arrow[data-astro-cid-amng4zvp]{width:24px;height:24px;color:var(--project-color);transition:all .3s ease;z-index:1}.project-link[data-astro-cid-amng4zvp]:hover{transform:translate(8px)}.project-link[data-astro-cid-amng4zvp]:hover .project-icon[data-astro-cid-amng4zvp],.project-link[data-astro-cid-amng4zvp]:hover .project-arrow[data-astro-cid-amng4zvp],.project-link[data-astro-cid-amng4zvp]:hover .project-name[data-astro-cid-amng4zvp]{color:var(--ctp-base)}@media(max-width:600px){.project[data-astro-cid-amng4zvp]{padding:4rem 2rem}.section-title[data-astro-cid-amng4zvp]{font-size:1.5rem;margin-bottom:2rem}.project-link[data-astro-cid-amng4zvp]{padding:1.25rem 1.5rem}.project-name[data-astro-cid-amng4zvp]{font-size:1.1rem}}.spotify[data-astro-cid-a3qsdpjt]{padding:6rem 2rem;display:flex;justify-content:center}.content[data-astro-cid-a3qsdpjt]{max-width:600px;width:100%}.spotify-container[data-astro-cid-a3qsdpjt]{background-color:var(--ctp-surface0);border:2px solid var(--ctp-green);border-radius:12px;padding:2rem;min-height:200px}@media(max-width:600px){.spotify[data-astro-cid-a3qsdpjt]{padding:4rem 2rem}.spotify-container[data-astro-cid-a3qsdpjt]{padding:1.5rem}}.project[data-astro-cid-4lhuo7md]{padding:6rem 2rem;display:flex;justify-content:center}.content[data-astro-cid-4lhuo7md]{max-width:600px;width:100%}.section-title[data-astro-cid-4lhuo7md]{font-size:2rem;font-weight:600;color:var(--ctp-text);margin-bottom:3rem;text-align:center}.projects[data-astro-cid-4lhuo7md]{display:flex;flex-direction:column;gap:1.5rem}.project-link[data-astro-cid-4lhuo7md]{display:flex;align-items:center;gap:1rem;padding:1.5rem 2rem;background-color:var(--ctp-surface0);border:2px solid var(--project-color);border-radius:12px;text-decoration:none;color:var(--ctp-text);transition:all .3s ease;position:relative;overflow:hidden}.project-link[data-astro-cid-4lhuo7md]:before{content:"";position:absolute;inset:-1px;background-color:var(--project-color);transform:scaleX(0);transform-origin:left;transition:transform .4s cubic-bezier(.4,0,.2,1);z-index:0}.project-link[data-astro-cid-4lhuo7md]:hover:before{transform:scaleX(1)}.project-icon[data-astro-cid-4lhuo7md]{font-size:1.5rem;color:var(--project-color);transition:all .3s ease;z-index:1}.project-name[data-astro-cid-4lhuo7md]{flex:1;font-size:1.25rem;font-weight:500;z-index:1;transition:color .3s ease}.project-arrow[data-astro-cid-4lhuo7md]{width:24px;height:24px;color:var(--project-color);transition:all .3s ease;z-index:1}.project-link[data-astro-cid-4lhuo7md]:hover{transform:translate(8px)}.project-link[data-astro-cid-4lhuo7md]:hover .project-icon[data-astro-cid-4lhuo7md],.project-link[data-astro-cid-4lhuo7md]:hover .project-arrow[data-astro-cid-4lhuo7md],.project-link[data-astro-cid-4lhuo7md]:hover .project-name[data-astro-cid-4lhuo7md]{color:var(--ctp-base)}@media(max-width:600px){.project[data-astro-cid-4lhuo7md]{padding:4rem 2rem}.section-title[data-astro-cid-4lhuo7md]{font-size:1.5rem;margin-bottom:2rem}.project-link[data-astro-cid-4lhuo7md]{padding:1.25rem 1.5rem}.project-name[data-astro-cid-4lhuo7md]{font-size:1.1rem}}

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -1,19 +0,0 @@
// @ts-check
import netlify from "@astrojs/netlify";
import react from "@astrojs/react";
import { defineConfig, envField } from "astro/config";
import vtbot from "astro-vtbot";
// https://astro.build/config
export default defineConfig({
integrations: [react(), vtbot()],
adapter: netlify(),
env: {
schema: {
CLIENT_ID: envField.string({ context: "server", access: "secret" }),
CLIENT_SECRET: envField.string({ context: "server", access: "secret" }),
REFRESH_TOKEN: envField.string({ context: "server", access: "secret" }),
},
},
});

6
blog/index.html Normal file
View File

@ -0,0 +1,6 @@
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width"><link rel="icon" type="image/png" href="/profilePicture.png"><meta name="generator" content="Astro v5.14.5"><meta name="darkreader-lock"><title>Kristian Emil Takvam</title><style>:root{--ctp-rosewater: #f5e0dc;--ctp-flamingo: #f2cdcd;--ctp-pink: #f5c2e7;--ctp-mauve: #cba6f7;--ctp-red: #f38ba8;--ctp-maroon: #eba0ac;--ctp-peach: #fab387;--ctp-yellow: #f9e2af;--ctp-green: #a6e3a1;--ctp-teal: #94e2d5;--ctp-sky: #89dceb;--ctp-sapphire: #74c7ec;--ctp-blue: #89b4fa;--ctp-lavender: #b4befe;--ctp-text: #cdd6f4;--ctp-subtext1: #bac2de;--ctp-subtext0: #a6adc8;--ctp-overlay2: #9399b2;--ctp-overlay1: #7f849c;--ctp-overlay0: #6c7086;--ctp-surface2: #585b70;--ctp-surface1: #45475a;--ctp-surface0: #313244;--ctp-base: #1e1e2e;--ctp-mantle: #181825;--ctp-crust: #11111b}*{margin:0;padding:0;box-sizing:border-box}body{background-color:var(--ctp-base);color:var(--ctp-text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;line-height:1.6}.intro[data-astro-cid-u43ozx4m]{padding:8rem 2rem 6rem;display:flex;justify-content:center}.content[data-astro-cid-u43ozx4m]{max-width:600px;width:100%;display:flex;align-items:center;gap:2rem}.pfp[data-astro-cid-u43ozx4m]{width:120px;height:120px;border-radius:50%;border:3px solid var(--ctp-lavender);transition:transform .3s ease,border-color .3s ease}.pfp[data-astro-cid-u43ozx4m]:hover{transform:scale(1.05);border-color:var(--ctp-pink)}.text[data-astro-cid-u43ozx4m]{flex:1}h1[data-astro-cid-u43ozx4m]{font-size:2rem;font-weight:600;color:var(--ctp-text);margin-bottom:.5rem}.subtitle[data-astro-cid-u43ozx4m]{font-size:1rem;color:var(--ctp-subtext0);opacity:.8}@media(max-width:600px){.intro[data-astro-cid-u43ozx4m]{padding:4rem 2rem 3rem}.content[data-astro-cid-u43ozx4m]{flex-direction:column;text-align:center}.pfp[data-astro-cid-u43ozx4m]{width:100px;height:100px}h1[data-astro-cid-u43ozx4m]{font-size:1.5rem}}.wave-container[data-astro-cid-5baqliqx]{width:100%;padding:3rem 2rem;display:flex;justify-content:center}.wave-wrapper[data-astro-cid-5baqliqx]{max-width:600px;width:100%;height:40px;overflow:hidden;position:relative;mask-image:linear-gradient(to right,transparent 0%,black 8%,black 92%,transparent 100%);-webkit-mask-image:linear-gradient(to right,transparent 0%,black 8%,black 92%,transparent 100%)}.wave[data-astro-cid-5baqliqx]{width:300%;height:100%;position:absolute;left:-100%}.wave-path[data-astro-cid-5baqliqx]{vector-effect:non-scaling-stroke}.wave-slide-left[data-astro-cid-5baqliqx]{animation:wave-slide-left var(--wave-speed) linear infinite}.wave-slide-right[data-astro-cid-5baqliqx]{animation:wave-slide-right var(--wave-speed) linear infinite}@keyframes wave-slide-left{0%{transform:translate(0)}to{transform:translate(-33.33%)}}@keyframes wave-slide-right{0%{transform:translate(-33.33%)}to{transform:translate(0)}}@media(max-width:600px){.wave-container[data-astro-cid-5baqliqx]{padding:2rem 1rem}}.socials[data-astro-cid-upu6fzxr]{padding:4rem 2rem 8rem;display:flex;justify-content:center}.content[data-astro-cid-upu6fzxr]{max-width:600px;width:100%;display:flex;justify-content:center}.social-links[data-astro-cid-upu6fzxr]{display:flex;gap:2rem;justify-content:center}.social-link[data-astro-cid-upu6fzxr]{width:60px;height:60px;display:flex;align-items:center;justify-content:center;background-color:var(--ctp-surface0);border:2px solid var(--social-color);border-radius:50%;color:var(--social-color);transition:all .3s cubic-bezier(.4,0,.2,1);text-decoration:none}.social-icon[data-astro-cid-upu6fzxr]{width:32px;height:32px;display:flex;align-items:center;justify-content:center}.social-icon[data-astro-cid-upu6fzxr] svg{width:100%;height:100%}.social-link[data-astro-cid-upu6fzxr]:hover{background-color:var(--social-color);color:var(--ctp-base);transform:translateY(-4px) rotate(5deg);box-shadow:0 8px 16px #0000004d}.social-link[data-astro-cid-upu6fzxr]:active{transform:translateY(-2px) rotate(5deg)}@media(max-width:600px){.socials[data-astro-cid-upu6fzxr]{padding:3rem 2rem 6rem}.social-links[data-astro-cid-upu6fzxr]{gap:1.5rem}.social-link[data-astro-cid-upu6fzxr]{width:56px;height:56px}.social-icon[data-astro-cid-upu6fzxr]{width:28px;height:28px}}
.blog-list[data-astro-cid-35dpazjw]{padding:3rem 2rem;display:flex;justify-content:center}.content[data-astro-cid-35dpazjw]{max-width:800px;width:100%}.posts[data-astro-cid-35dpazjw]{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1.5rem}.post-item[data-astro-cid-35dpazjw]{padding:1.5rem;background-color:var(--ctp-surface0);border:2px solid var(--ctp-lavender);border-radius:12px;transition:transform .2s ease,border-color .2s ease}.post-item[data-astro-cid-35dpazjw]:hover{transform:translateY(-2px);border-color:var(--ctp-pink)}.post-link[data-astro-cid-35dpazjw]{display:flex;flex-direction:column;gap:.4rem;text-decoration:none}.post-title[data-astro-cid-35dpazjw]{font-size:1.3rem;font-weight:600;color:var(--ctp-text)}.post-description[data-astro-cid-35dpazjw]{color:var(--ctp-subtext0);font-size:.95rem}.post-date[data-astro-cid-35dpazjw]{color:var(--ctp-subtext0);font-size:.85rem;opacity:.7}@media(max-width:600px){.blog-list[data-astro-cid-35dpazjw]{padding:2rem 1rem}.post-item[data-astro-cid-35dpazjw]{padding:1rem}}
</style></head> <body> <main> <section class="intro" data-astro-cid-u43ozx4m> <div class="content" data-astro-cid-u43ozx4m> <a href="/" data-astro-cid-u43ozx4m> <img src="/_astro/profile-picture.C8jVU_ub.png" alt="trueberryless" class="pfp" data-astro-cid-u43ozx4m> </a> <div class="text" data-astro-cid-u43ozx4m> <h1 data-astro-cid-u43ozx4m>Kristian Emil Takvam</h1> <p class="subtitle" data-astro-cid-u43ozx4m>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent lobortis nisi ante, nec tincidunt ligula mattis nec. Maecenas metus mauris, fermentum et vulputate ut, dapibus vel massa.</p> </div> </div> </section> <div class="wave-container" data-astro-cid-5baqliqx> <div class="wave-wrapper" style="--wave-speed: 100s" data-astro-cid-5baqliqx> <svg class="wave wave-slide-left" viewBox="0 0 600 40" preserveAspectRatio="none" data-astro-cid-5baqliqx> <path class="wave-path" d="M 0,20 Q 4,10.399999999999999 8,20 Q 12,29.6 16,20 Q 20,10.399999999999999 24,20 Q 28,29.6 32,20 Q 36,10.399999999999999 40,20 Q 44,29.6 48,20 Q 52,10.399999999999999 56,20 Q 60,29.6 64,20 Q 68,10.399999999999999 72,20 Q 76,29.6 80,20 Q 84,10.399999999999999 88,20 Q 92,29.6 96,20 Q 100,10.399999999999999 104,20 Q 108,29.6 112,20 Q 116,10.399999999999999 120,20 Q 124,29.6 128,20 Q 132,10.399999999999999 136,20 Q 140,29.6 144,20 Q 148,10.399999999999999 152,20 Q 156,29.6 160,20 Q 164,10.399999999999999 168,20 Q 172,29.6 176,20 Q 180,10.399999999999999 184,20 Q 188,29.6 192,20 Q 196,10.399999999999999 200,20 Q 204,29.6 208,20 Q 212,10.399999999999999 216,20 Q 220,29.6 224,20 Q 228,10.399999999999999 232,20 Q 236,29.6 240,20 Q 244,10.399999999999999 248,20 Q 252,29.6 256,20 Q 260,10.399999999999999 264,20 Q 268,29.6 272,20 Q 276,10.399999999999999 280,20 Q 284,29.6 288,20 Q 292,10.399999999999999 296,20 Q 300,29.6 304,20 Q 308,10.399999999999999 312,20 Q 316,29.6 320,20 Q 324,10.399999999999999 328,20 Q 332,29.6 336,20 Q 340,10.399999999999999 344,20 Q 348,29.6 352,20 Q 356,10.399999999999999 360,20 Q 364,29.6 368,20 Q 372,10.399999999999999 376,20 Q 380,29.6 384,20 Q 388,10.399999999999999 392,20 Q 396,29.6 400,20 Q 404,10.399999999999999 408,20 Q 412,29.6 416,20 Q 420,10.399999999999999 424,20 Q 428,29.6 432,20 Q 436,10.399999999999999 440,20 Q 444,29.6 448,20 Q 452,10.399999999999999 456,20 Q 460,29.6 464,20 Q 468,10.399999999999999 472,20 Q 476,29.6 480,20 Q 484,10.399999999999999 488,20 Q 492,29.6 496,20 Q 500,10.399999999999999 504,20 Q 508,29.6 512,20 Q 516,10.399999999999999 520,20 Q 524,29.6 528,20 Q 532,10.399999999999999 536,20 Q 540,29.6 544,20 Q 548,10.399999999999999 552,20 Q 556,29.6 560,20 Q 564,10.399999999999999 568,20 Q 572,29.6 576,20 Q 580,10.399999999999999 584,20 Q 588,29.6 592,20 Q 596,10.399999999999999 600,20 Q 604,29.6 608,20 Q 612,10.399999999999999 616,20 Q 620,29.6 624,20 Q 628,10.399999999999999 632,20 Q 636,29.6 640,20 Q 644,10.399999999999999 648,20 Q 652,29.6 656,20 Q 660,10.399999999999999 664,20 Q 668,29.6 672,20 Q 676,10.399999999999999 680,20 Q 684,29.6 688,20 Q 692,10.399999999999999 696,20 Q 700,29.6 704,20 Q 708,10.399999999999999 712,20 Q 716,29.6 720,20 Q 724,10.399999999999999 728,20 Q 732,29.6 736,20 Q 740,10.399999999999999 744,20 Q 748,29.6 752,20 Q 756,10.399999999999999 760,20 Q 764,29.6 768,20 Q 772,10.399999999999999 776,20 Q 780,29.6 784,20 Q 788,10.399999999999999 792,20 Q 796,29.6 800,20 Q 804,10.399999999999999 808,20 Q 812,29.6 816,20 Q 820,10.399999999999999 824,20 Q 828,29.6 832,20 Q 836,10.399999999999999 840,20 Q 844,29.6 848,20 Q 852,10.399999999999999 856,20 Q 860,29.6 864,20 Q 868,10.399999999999999 872,20 Q 876,29.6 880,20 Q 884,10.399999999999999 888,20 Q 892,29.6 896,20 Q 900,10.399999999999999 904,20 Q 908,29.6 912,20 Q 916,10.399999999999999 920,20 Q 924,29.6 928,20 Q 932,10.399999999999999 936,20 Q 940,29.6 944,20 Q 948,10.399999999999999 952,20 Q 956,29.6 960,20" stroke="var(--ctp-rosewater)" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-5baqliqx></path> </svg> </div> </div> <!--
<Posts />
<WaveDivider color="teal" speed={100} size={0.8} direction="left" />
--> <section class="blog-list" data-astro-cid-35dpazjw> <div class="content" data-astro-cid-35dpazjw> <ul class="posts" data-astro-cid-35dpazjw> </ul> </div> </section> <!-- Use the new component --> <section class="socials" data-astro-cid-upu6fzxr> <div class="content" data-astro-cid-upu6fzxr> <div class="social-links" data-astro-cid-upu6fzxr> <a href="https://github.com/Kremtastic" class="social-link" target="_blank" rel="noopener noreferrer" style="--social-color: var(--ctp-sapphire)" aria-label="GitHub" data-astro-cid-upu6fzxr> <span class="social-icon" data-astro-cid-upu6fzxr><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12c0 4.42 2.865 8.17 6.839 9.49.5.092.682-.217.682-.482 0-.237-.008-.866-.013-1.7-2.782.603-3.369-1.34-3.369-1.34-.454-1.156-1.11-1.463-1.11-1.463-.908-.62.069-.608.069-.608 1.003.07 1.531 1.03 1.531 1.03.892 1.529 2.341 1.087 2.91.831.092-.646.35-1.086.636-1.336-2.22-.253-4.555-1.11-4.555-4.943 0-1.091.39-1.984 1.029-2.683-.103-.253-.446-1.27.098-2.647 0 0 .84-.269 2.75 1.025A9.578 9.578 0 0112 6.836c.85.004 1.705.114 2.504.336 1.909-1.294 2.747-1.025 2.747-1.025.546 1.377.203 2.394.1 2.647.64.699 1.028 1.592 1.028 2.683 0 3.842-2.339 4.687-4.566 4.935.359.309.678.919.678 1.852 0 1.336-.012 2.415-.012 2.743 0 .267.18.578.688.48C19.138 20.167 22 16.418 22 12c0-5.523-4.477-10-10-10z"/></svg></span> </a><a href="https://www.linkedin.com/in/kristian-emil-takvam-70a475215" class="social-link" target="_blank" rel="noopener noreferrer" style="--social-color: var(--ctp-blue)" aria-label="LinkedIn" data-astro-cid-upu6fzxr> <span class="social-icon" data-astro-cid-upu6fzxr><svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg></span> </a><a href="/rss.xml" class="social-link" target="_blank" rel="noopener noreferrer" style="--social-color: var(--ctp-peach)" aria-label="RSS" data-astro-cid-upu6fzxr> <span class="social-icon" data-astro-cid-upu6fzxr><svg viewBox="0 0 22 24" fill="currentColor"><circle cx="6.18" cy="17.82" r="2.18"/><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9z"/></svg></span> </a> </div> </div> </section> </main> </body></html>

5
index.html Normal file

File diff suppressed because one or more lines are too long

11848
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +0,0 @@
{
"name": "trueberryless",
"homepage": "https://github.com/trueberryless-org/trueberryless",
"bugs": {
"url": "https://github.com/trueberryless-org/trueberryless/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/trueberryless-org/trueberryless.git"
},
"license": "MIT",
"author": "trueberryless <trueberryless@gmail.com> (https://trueberryless.org)",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/netlify": "^6.5.11",
"@astrojs/react": "^4.4.0",
"@types/react": "^19.1.16",
"@types/react-dom": "^19.1.9",
"astro-vtbot": "^2.1.9",
"astro-webrings": "^0.1.1",
"react": "^19.1.1",
"react-dom": "^19.1.1"
},
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "5.2.2",
"astro": "^5.14.5",
"prettier": "3.5.3",
"prettier-plugin-astro": "0.14.1"
},
"packageManager": "pnpm@10.10.0"
}

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

@ -1,86 +0,0 @@
---
import { getCollection } from "astro:content";
const posts = await getCollection("blog");
const sortedPosts = posts.sort(
(a, b) => b.data.date.getTime() - a.data.date.getTime()
);
---
<section class="blog-list">
<div class="content">
<ul class="posts">
{sortedPosts.map((post) => (
<li class="post-item">
<a href={`/blog/${post.slug}`} class="post-link">
<span class="post-title">{post.data.title}</span>
{post.data.description && (
<span class="post-description">{post.data.description}</span>
)}
<span class="post-date">{post.data.date.toDateString()}</span>
</a>
</li>
))}
</ul>
</div>
</section>
<style>
.blog-list {
padding: 3rem 2rem;
display: flex;
justify-content: center;
}
.content {
max-width: 800px;
width: 100%;
}
.posts {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.post-item {
padding: 1.5rem;
background-color: var(--ctp-surface0);
border: 2px solid var(--ctp-lavender);
border-radius: 12px;
transition: transform 0.2s ease, border-color 0.2s ease;
}
.post-item:hover {
transform: translateY(-2px);
border-color: var(--ctp-pink);
}
.post-link {
display: flex;
flex-direction: column;
gap: 0.4rem;
text-decoration: none;
}
.post-title {
font-size: 1.3rem;
font-weight: 600;
color: var(--ctp-text);
}
.post-description {
color: var(--ctp-subtext0);
font-size: 0.95rem;
}
.post-date {
color: var(--ctp-subtext0);
font-size: 0.85rem;
opacity: 0.7;
}
@media (max-width: 600px) {
.blog-list {
padding: 2rem 1rem;
}
.post-item {
padding: 1rem;
}
}
</style>

View File

@ -1,154 +0,0 @@
---
// TODO: List some projects
const projects = [
{
name: "Blog",
url: "/blog",
color: "var(--ctp-lavender)",
},
];
---
<section class="project">
<div class="content">
<h2 class="section-title">Blog</h2>
<div class="projects">
{
projects.map((project) => (
<a
href={project.url}
class="project-link"
target=""
rel="noopener noreferrer"
style={`--project-color: ${project.color}`}
>
<span class="project-icon">◈</span>
<span class="project-name">{project.name}</span>
<svg class="project-arrow" viewBox="0 0 24 24" fill="none">
<path
d="M7 17L17 7M17 7H7M17 7V17"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</a>
))
}
</div>
</div>
</section>
<style>
.project {
padding: 6rem 2rem;
display: flex;
justify-content: center;
}
.content {
max-width: 600px;
width: 100%;
}
.section-title {
font-size: 2rem;
font-weight: 600;
color: var(--ctp-text);
margin-bottom: 3rem;
text-align: center;
}
.projects {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.project-link {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.5rem 2rem;
background-color: var(--ctp-surface0);
border: 2px solid var(--project-color);
border-radius: 12px;
text-decoration: none;
color: var(--ctp-text);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.project-link::before {
content: "";
position: absolute;
inset: -1px;
background-color: var(--project-color);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 0;
}
.project-link:hover::before {
transform: scaleX(1);
}
.project-icon {
font-size: 1.5rem;
color: var(--project-color);
transition: all 0.3s ease;
z-index: 1;
}
.project-name {
flex: 1;
font-size: 1.25rem;
font-weight: 500;
z-index: 1;
transition: color 0.3s ease;
}
.project-arrow {
width: 24px;
height: 24px;
color: var(--project-color);
transition: all 0.3s ease;
z-index: 1;
}
.project-link:hover {
transform: translateX(8px);
}
.project-link:hover .project-icon,
.project-link:hover .project-arrow {
color: var(--ctp-base);
}
.project-link:hover .project-name {
color: var(--ctp-base);
}
@media (max-width: 600px) {
.project {
padding: 4rem 2rem;
}
.section-title {
font-size: 1.5rem;
margin-bottom: 2rem;
}
.project-link {
padding: 1.25rem 1.5rem;
}
.project-name {
font-size: 1.1rem;
}
}
</style>

View File

@ -1,90 +0,0 @@
---
import profilePicture from "../assets/profile-picture.png";
interface Props {
name: string;
subtitle: string;
}
const { name, subtitle } = Astro.props;
---
<section class="intro">
<div class="content">
<a href="/">
<img src={profilePicture.src} alt="trueberryless" class="pfp" />
</a>
<div class="text">
<h1>{name}</h1>
<p class="subtitle">{subtitle}</p>
</div>
</div>
</section>
<style>
.intro {
padding: 8rem 2rem 6rem;
display: flex;
justify-content: center;
}
.content {
max-width: 600px;
width: 100%;
display: flex;
align-items: center;
gap: 2rem;
}
.pfp {
width: 120px;
height: 120px;
border-radius: 50%;
border: 3px solid var(--ctp-lavender);
transition:
transform 0.3s ease,
border-color 0.3s ease;
}
.pfp:hover {
transform: scale(1.05);
border-color: var(--ctp-pink);
}
.text {
flex: 1;
}
h1 {
font-size: 2rem;
font-weight: 600;
color: var(--ctp-text);
margin-bottom: 0.5rem;
}
.subtitle {
font-size: 1rem;
color: var(--ctp-subtext0);
opacity: 0.8;
}
@media (max-width: 600px) {
.intro {
padding: 4rem 2rem 3rem;
}
.content {
flex-direction: column;
text-align: center;
}
.pfp {
width: 100px;
height: 100px;
}
h1 {
font-size: 1.5rem;
}
}
</style>

View File

@ -1,111 +0,0 @@
---
import { getCollection } from 'astro:content';
// Get all blog posts from your content collection
const posts = await getCollection('blog');
// Sort by date if you have a date field in frontmatter
const sortedPosts = posts.sort((a, b) =>
b.data.date.getTime() - a.data.date.getTime()
);
---
<section class="project">
<div class="content">
<h2 class="section-title">Blog</h2>
<div class="posts">
{
await Promise.all(sortedPosts.map(async (post) => {
const { Content } = await post.render();
return (
<article class="post">
<h3 class="post-title">{post.data.title}</h3>
<div class="post-content">
<Content />
</div>
</article>
);
}))
}
</div>
</div>
</section>
<style>
.project {
padding: 6rem 2rem;
display: flex;
justify-content: center;
}
.content {
max-width: 800px;
width: 100%;
}
.section-title {
font-size: 2rem;
font-weight: 600;
color: var(--ctp-text);
margin-bottom: 3rem;
text-align: center;
}
.posts {
display: flex;
flex-direction: column;
gap: 3rem;
}
.post {
padding: 2rem;
background-color: var(--ctp-surface0);
border: 2px solid var(--ctp-lavender);
border-radius: 12px;
}
.post-title {
font-size: 1.5rem;
font-weight: 600;
color: var(--ctp-text);
margin-bottom: 1.5rem;
}
.post-content {
color: var(--ctp-text);
line-height: 1.6;
}
/* Style markdown content */
.post-content :global(p) {
margin-bottom: 1rem;
}
.post-content :global(h1),
.post-content :global(h2),
.post-content :global(h3) {
margin-top: 1.5rem;
margin-bottom: 1rem;
color: var(--ctp-lavender);
}
.post-content :global(code) {
background-color: var(--ctp-mantle);
padding: 0.2rem 0.4rem;
border-radius: 4px;
}
@media (max-width: 600px) {
.project {
padding: 4rem 1rem;
}
.section-title {
font-size: 1.5rem;
margin-bottom: 2rem;
}
.post {
padding: 1.5rem;
}
}
</style>

View File

@ -1,158 +0,0 @@
---
// TODO: List some projects
const projects = [
{
name: "Portal Room",
url: "https://github.com/Kremtastic/PortalRoom",
color: "var(--ctp-lavender)",
},
{
name: "Raytracer",
url: "https://github.com/Kremtastic/RaytracerUnity",
color: "var(--ctp-peach)",
},
];
---
<section class="project">
<div class="content">
<h2 class="section-title">Projects</h2>
<div class="projects">
{
projects.map((project) => (
<a
href={project.url}
class="project-link"
target="_blank"
rel="noopener noreferrer"
style={`--project-color: ${project.color}`}
>
<span class="project-icon">◈</span>
<span class="project-name">{project.name}</span>
<svg class="project-arrow" viewBox="0 0 24 24" fill="none">
<path
d="M7 17L17 7M17 7H7M17 7V17"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</a>
))
}
</div>
</div>
</section>
<style>
.project {
padding: 6rem 2rem;
display: flex;
justify-content: center;
}
.content {
max-width: 600px;
width: 100%;
}
.section-title {
font-size: 2rem;
font-weight: 600;
color: var(--ctp-text);
margin-bottom: 3rem;
text-align: center;
}
.projects {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.project-link {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.5rem 2rem;
background-color: var(--ctp-surface0);
border: 2px solid var(--project-color);
border-radius: 12px;
text-decoration: none;
color: var(--ctp-text);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.project-link::before {
content: "";
position: absolute;
inset: -1px;
background-color: var(--project-color);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 0;
}
.project-link:hover::before {
transform: scaleX(1);
}
.project-icon {
font-size: 1.5rem;
color: var(--project-color);
transition: all 0.3s ease;
z-index: 1;
}
.project-name {
flex: 1;
font-size: 1.25rem;
font-weight: 500;
z-index: 1;
transition: color 0.3s ease;
}
.project-arrow {
width: 24px;
height: 24px;
color: var(--project-color);
transition: all 0.3s ease;
z-index: 1;
}
.project-link:hover {
transform: translateX(8px);
}
.project-link:hover .project-icon,
.project-link:hover .project-arrow {
color: var(--ctp-base);
}
.project-link:hover .project-name {
color: var(--ctp-base);
}
@media (max-width: 600px) {
.project {
padding: 4rem 2rem;
}
.section-title {
font-size: 1.5rem;
margin-bottom: 2rem;
}
.project-link {
padding: 1.25rem 1.5rem;
}
.project-name {
font-size: 1.1rem;
}
}
</style>

View File

@ -1,124 +0,0 @@
---
// TODO: Adapt social links
const socials = [
{
name: "GitHub",
url: "https://github.com/Kremtastic",
color: "var(--ctp-sapphire)",
icon: `<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12c0 4.42 2.865 8.17 6.839 9.49.5.092.682-.217.682-.482 0-.237-.008-.866-.013-1.7-2.782.603-3.369-1.34-3.369-1.34-.454-1.156-1.11-1.463-1.11-1.463-.908-.62.069-.608.069-.608 1.003.07 1.531 1.03 1.531 1.03.892 1.529 2.341 1.087 2.91.831.092-.646.35-1.086.636-1.336-2.22-.253-4.555-1.11-4.555-4.943 0-1.091.39-1.984 1.029-2.683-.103-.253-.446-1.27.098-2.647 0 0 .84-.269 2.75 1.025A9.578 9.578 0 0112 6.836c.85.004 1.705.114 2.504.336 1.909-1.294 2.747-1.025 2.747-1.025.546 1.377.203 2.394.1 2.647.64.699 1.028 1.592 1.028 2.683 0 3.842-2.339 4.687-4.566 4.935.359.309.678.919.678 1.852 0 1.336-.012 2.415-.012 2.743 0 .267.18.578.688.48C19.138 20.167 22 16.418 22 12c0-5.523-4.477-10-10-10z"/></svg>`,
},
{
name: "LinkedIn",
url: "https://www.linkedin.com/in/kristian-emil-takvam-70a475215",
color: "var(--ctp-blue)",
icon: `<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>`,
},
{
name: "RSS",
url: "/rss.xml",
color: "var(--ctp-peach)",
icon: `<svg viewBox="0 0 22 24" fill="currentColor"><circle cx="6.18" cy="17.82" r="2.18"/><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9z"/></svg>`,
},
];
---
<section class="socials">
<div class="content">
<div class="social-links">
{
socials.map((social) => (
<a
href={social.url}
class="social-link"
target="_blank"
rel="noopener noreferrer"
style={`--social-color: ${social.color}`}
aria-label={social.name}
>
<span class="social-icon" set:html={social.icon} />
</a>
))
}
</div>
</div>
</section>
<style>
.socials {
padding: 4rem 2rem 8rem;
display: flex;
justify-content: center;
}
.content {
max-width: 600px;
width: 100%;
display: flex;
justify-content: center;
}
.social-links {
display: flex;
gap: 2rem;
justify-content: center;
}
.social-link {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--ctp-surface0);
border: 2px solid var(--social-color);
border-radius: 50%;
color: var(--social-color);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
text-decoration: none;
}
.social-icon {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
}
.social-icon :global(svg) {
width: 100%;
height: 100%;
}
.social-link:hover {
background-color: var(--social-color);
color: var(--ctp-base);
transform: translateY(-4px) rotate(5deg);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
}
.social-link:active {
transform: translateY(-2px) rotate(5deg);
}
@media (max-width: 600px) {
.socials {
padding: 3rem 2rem 6rem;
}
.social-links {
gap: 1.5rem;
}
.social-link {
width: 56px;
height: 56px;
}
.social-icon {
width: 28px;
height: 28px;
}
}
</style>

View File

@ -1,70 +0,0 @@
import { useEffect, useState } from "react";
const SoundWave = ({ progress, isPlaying }) => {
const [animationTimings, setAnimationTimings] = useState([]);
useEffect(() => {
const timings = [];
for (let i = 0; i < 50; i++) {
timings.push(Math.floor(Math.random() * 800) + 700);
}
setAnimationTimings(timings);
}, []);
const createLines = () => {
const progressNum = Math.floor(progress / 2);
const lines = [];
const y1 = isPlaying ? 3 : 8;
const y2 = isPlaying ? 25 : 20;
for (let i = 1; i < 51; i++) {
const isFull = i <= progressNum;
lines.push(
<line
key={i}
x1={i + i * 6}
y1={y1}
x2={i + i * 6}
y2={y2}
strokeWidth="2"
stroke={isFull ? "var(--ctp-green)" : "var(--ctp-overlay0)"}
style={{
transformOrigin: "center",
transition: "stroke 1s ease-in-out",
animation: isPlaying
? `sound ${animationTimings[i]}ms linear infinite alternate`
: "none",
}}
/>
);
}
return lines;
};
return (
<div>
<svg
width="302"
height="28"
viewBox="0 0 344 28"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={{ maxWidth: "100%", height: "auto" }}
>
{createLines()}
</svg>
<style>{`
@keyframes sound {
0% {
transform: scaleY(0.4);
}
100% {
transform: scaleY(1);
}
}
`}</style>
</div>
);
};
export default SoundWave;

View File

@ -1,42 +0,0 @@
---
import SpotifyPlayer from "./SpotifyPlayer";
---
<section class="spotify">
<div class="content">
<div class="spotify-container">
<SpotifyPlayer client:only="react" />
</div>
</div>
</section>
<style>
.spotify {
padding: 6rem 2rem;
display: flex;
justify-content: center;
}
.content {
max-width: 600px;
width: 100%;
}
.spotify-container {
background-color: var(--ctp-surface0);
border: 2px solid var(--ctp-green);
border-radius: 12px;
padding: 2rem;
min-height: 200px;
}
@media (max-width: 600px) {
.spotify {
padding: 4rem 2rem;
}
.spotify-container {
padding: 1.5rem;
}
}
</style>

View File

@ -1,165 +0,0 @@
import { useEffect, useState } from "react";
import SoundWave from "./SoundWave";
const SpotifyPlayer = () => {
const [track, setTrack] = useState(null);
const [isPlaying, setIsPlaying] = useState(false);
const [loading, setLoading] = useState(true);
const [progress, setProgress] = useState(0);
useEffect(() => {
const fetchNowPlaying = async () => {
try {
const response = await fetch("/api/spotify/now-playing");
if (response.status === 204) {
setTrack(null);
setIsPlaying(false);
setLoading(false);
return;
}
const data = await response.json();
setTrack(data);
setIsPlaying(data.isPlaying);
setProgress(data.progress || 0);
setLoading(false);
} catch (error) {
console.error("Error fetching now playing:", error);
setLoading(false);
}
};
fetchNowPlaying();
const interval = setInterval(fetchNowPlaying, 10000);
return () => clearInterval(interval);
}, []);
if (loading) {
return (
<div style={{ textAlign: "center", color: "var(--ctp-subtext0)" }}>
Loading...
</div>
);
}
if (!track) {
return (
<div style={{ textAlign: "center", color: "var(--ctp-subtext0)" }}>
<svg
width="64"
height="64"
viewBox="0 0 24 24"
fill="none"
style={{ margin: "0 auto 1rem", color: "var(--ctp-green)" }}
>
<path
d="M9 18V5l12-2v13M9 18c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3zm12-2c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3z"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
<p>Not playing anything right now</p>
</div>
);
}
return (
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
<div style={{ display: "flex", gap: "1.5rem", alignItems: "center" }}>
{track.albumArt && (
<img
src={track.albumArt}
alt={track.album}
style={{
width: "80px",
height: "80px",
borderRadius: "8px",
border: "2px solid var(--ctp-green)",
}}
/>
)}
<div style={{ flex: 1, minWidth: 0 }}>
<div
style={{
fontSize: "1.25rem",
fontWeight: "600",
color: "var(--ctp-text)",
marginBottom: "0.25rem",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{track.title}
</div>
<div
style={{
fontSize: "1rem",
color: "var(--ctp-subtext0)",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{track.artist}
</div>
{track.album && (
<div
style={{
fontSize: "0.9rem",
color: "var(--ctp-subtext1)",
marginTop: "0.25rem",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{track.album}
</div>
)}
</div>
</div>
<div style={{ display: "flex", justifyContent: "center" }}>
<SoundWave progress={progress} isPlaying={isPlaying} />
</div>
{track.trackUrl && (
<a
href={track.trackUrl}
target="_blank"
rel="noopener noreferrer"
style={{
display: "inline-flex",
alignItems: "center",
gap: "0.5rem",
padding: "0.75rem 1.5rem",
backgroundColor: "var(--ctp-green)",
color: "var(--ctp-base)",
borderRadius: "9999px",
textDecoration: "none",
fontWeight: "500",
alignSelf: "center",
transition: "all 0.3s ease",
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = "scale(1.05)";
e.currentTarget.style.backgroundColor = "var(--ctp-teal)";
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = "scale(1)";
e.currentTarget.style.backgroundColor = "var(--ctp-green)";
}}
>
Open in Spotify
</a>
)}
</div>
);
};
export default SpotifyPlayer;

View File

@ -1,144 +0,0 @@
---
interface Props {
color: string;
speed?: number; // Duration in seconds, default 60
size?: number; // Circle size multiplier, default 1
direction?: "left" | "right"; // Animation direction, default 'left'
}
const { color, speed = 60, size = 1, direction = "left" } = Astro.props;
const colorMap: any = {
rosewater: "var(--ctp-rosewater)",
flamingo: "var(--ctp-flamingo)",
pink: "var(--ctp-pink)",
mauve: "var(--ctp-mauve)",
red: "var(--ctp-red)",
maroon: "var(--ctp-maroon)",
peach: "var(--ctp-peach)",
yellow: "var(--ctp-yellow)",
green: "var(--ctp-green)",
teal: "var(--ctp-teal)",
sky: "var(--ctp-sky)",
sapphire: "var(--ctp-sapphire)",
blue: "var(--ctp-blue)",
lavender: "var(--ctp-lavender)",
};
const waveColor = colorMap[color];
// Generate smooth wave pattern
const generateWavePath = () => {
let path = "M 0,20";
const circleWidth = 10 * size;
const amplitude = 12 * size;
const circles = 120;
for (let i = 0; i < circles; i++) {
const x = i * circleWidth;
const direction = i % 2 === 0 ? -1 : 1;
const y = 20 + amplitude * direction;
path += ` Q ${x + circleWidth / 2},${y} ${x + circleWidth},20`;
}
return path;
};
const wavePath = generateWavePath();
const animationClass =
direction === "left" ? "wave-slide-left" : "wave-slide-right";
---
<div class="wave-container">
<div class="wave-wrapper" style={`--wave-speed: ${speed}s`}>
<svg
class="wave"
class:list={[animationClass]}
viewBox="0 0 600 40"
preserveAspectRatio="none"
>
<path
class="wave-path"
d={wavePath}
stroke={waveColor}
stroke-width="3"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"></path>
</svg>
</div>
</div>
<style>
.wave-container {
width: 100%;
padding: 3rem 2rem;
display: flex;
justify-content: center;
}
.wave-wrapper {
max-width: 600px;
width: 100%;
height: 40px;
overflow: hidden;
position: relative;
mask-image: linear-gradient(
to right,
transparent 0%,
black 8%,
black 92%,
transparent 100%
);
-webkit-mask-image: linear-gradient(
to right,
transparent 0%,
black 8%,
black 92%,
transparent 100%
);
}
.wave {
width: 300%;
height: 100%;
position: absolute;
left: -100%;
}
.wave-path {
vector-effect: non-scaling-stroke;
}
.wave-slide-left {
animation: wave-slide-left var(--wave-speed) linear infinite;
}
.wave-slide-right {
animation: wave-slide-right var(--wave-speed) linear infinite;
}
@keyframes wave-slide-left {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-33.33%);
}
}
@keyframes wave-slide-right {
0% {
transform: translateX(-33.33%);
}
100% {
transform: translateX(0);
}
}
@media (max-width: 600px) {
.wave-container {
padding: 2rem 1rem;
}
}
</style>

View File

@ -1,153 +0,0 @@
---
// TODO: Adjust the webrings accoring to https://astro-webrings.lou.gg/ if you want.
const webrings = [
{
name: "Join the Astro webring (shoutouts to Lou)",
url: "https://astro-webrings.lou.gg/",
color: "var(--ctp-red)",
},
];
---
<section class="webring">
<div class="content">
<h2 class="section-title">Webrings</h2>
<div class="rings">
{
webrings.map((ring) => (
<a
href={ring.url}
class="ring-link"
target="_blank"
rel="noopener noreferrer"
style={`--ring-color: ${ring.color}`}
>
<span class="ring-icon">◈</span>
<span class="ring-name">{ring.name}</span>
<svg class="ring-arrow" viewBox="0 0 24 24" fill="none">
<path
d="M7 17L17 7M17 7H7M17 7V17"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</a>
))
}
</div>
</div>
</section>
<style>
.webring {
padding: 6rem 2rem;
display: flex;
justify-content: center;
}
.content {
max-width: 600px;
width: 100%;
}
.section-title {
font-size: 2rem;
font-weight: 600;
color: var(--ctp-text);
margin-bottom: 3rem;
text-align: center;
}
.rings {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.ring-link {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.5rem 2rem;
background-color: var(--ctp-surface0);
border: 2px solid var(--ring-color);
border-radius: 12px;
text-decoration: none;
color: var(--ctp-text);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.ring-link::before {
content: "";
position: absolute;
inset: -1px;
background-color: var(--ring-color);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
z-index: 0;
}
.ring-link:hover::before {
transform: scaleX(1);
}
.ring-icon {
font-size: 1.5rem;
color: var(--ring-color);
transition: all 0.3s ease;
z-index: 1;
}
.ring-name {
flex: 1;
font-size: 1.25rem;
font-weight: 500;
z-index: 1;
transition: color 0.3s ease;
}
.ring-arrow {
width: 24px;
height: 24px;
color: var(--ring-color);
transition: all 0.3s ease;
z-index: 1;
}
.ring-link:hover {
transform: translateX(8px);
}
.ring-link:hover .ring-icon,
.ring-link:hover .ring-arrow {
color: var(--ctp-base);
}
.ring-link:hover .ring-name {
color: var(--ctp-base);
}
@media (max-width: 600px) {
.webring {
padding: 4rem 2rem;
}
.section-title {
font-size: 1.5rem;
margin-bottom: 2rem;
}
.ring-link {
padding: 1.25rem 1.5rem;
}
.ring-name {
font-size: 1.1rem;
}
}
</style>

View File

@ -1,12 +0,0 @@
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
date: z.coerce.date(),
description: z.string().optional(),
}),
});
export const collections = { blog };

View File

@ -1,71 +0,0 @@
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/png" href="/profilePicture.png" />
<meta name="generator" content={Astro.generator} />
<meta name="darkreader-lock" />
<title>{title}</title>
</head>
<body>
<slot />
</body>
</html>
<style is:global>
/* TODO: Adjust the color scheme if you want
(recommendation: Catppuccin - https://catppuccin.com/palette/) */
:root {
/* Catppuccin Mocha */
--ctp-rosewater: #f5e0dc;
--ctp-flamingo: #f2cdcd;
--ctp-pink: #f5c2e7;
--ctp-mauve: #cba6f7;
--ctp-red: #f38ba8;
--ctp-maroon: #eba0ac;
--ctp-peach: #fab387;
--ctp-yellow: #f9e2af;
--ctp-green: #a6e3a1;
--ctp-teal: #94e2d5;
--ctp-sky: #89dceb;
--ctp-sapphire: #74c7ec;
--ctp-blue: #89b4fa;
--ctp-lavender: #b4befe;
--ctp-text: #cdd6f4;
--ctp-subtext1: #bac2de;
--ctp-subtext0: #a6adc8;
--ctp-overlay2: #9399b2;
--ctp-overlay1: #7f849c;
--ctp-overlay0: #6c7086;
--ctp-surface2: #585b70;
--ctp-surface1: #45475a;
--ctp-surface0: #313244;
--ctp-base: #1e1e2e;
--ctp-mantle: #181825;
--ctp-crust: #11111b;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: var(--ctp-base);
color: var(--ctp-text);
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
Cantarell, sans-serif;
line-height: 1.6;
}
</style>

View File

@ -1,71 +0,0 @@
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/png" href="/profilePicture.png" />
<meta name="generator" content={Astro.generator} />
<meta name="darkreader-lock" />
<title>{title}</title>
</head>
<body>
<slot />
</body>
</html>
<style is:global>
/* TODO: Adjust the color scheme if you want
(recommendation: Catppuccin - https://catppuccin.com/palette/) */
:root {
/* Catppuccin Mocha */
--ctp-rosewater: #f5e0dc;
--ctp-flamingo: #f2cdcd;
--ctp-pink: #f5c2e7;
--ctp-mauve: #cba6f7;
--ctp-red: #f38ba8;
--ctp-maroon: #eba0ac;
--ctp-peach: #fab387;
--ctp-yellow: #f9e2af;
--ctp-green: #a6e3a1;
--ctp-teal: #94e2d5;
--ctp-sky: #89dceb;
--ctp-sapphire: #74c7ec;
--ctp-blue: #89b4fa;
--ctp-lavender: #b4befe;
--ctp-text: #cdd6f4;
--ctp-subtext1: #bac2de;
--ctp-subtext0: #a6adc8;
--ctp-overlay2: #9399b2;
--ctp-overlay1: #7f849c;
--ctp-overlay0: #6c7086;
--ctp-surface2: #585b70;
--ctp-surface1: #45475a;
--ctp-surface0: #313244;
--ctp-base: #1e1e2e;
--ctp-mantle: #181825;
--ctp-crust: #11111b;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: var(--ctp-base);
color: var(--ctp-text);
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
Cantarell, sans-serif;
line-height: 1.6;
}
</style>

View File

@ -1,81 +0,0 @@
// src/pages/api/spotify/now-playing.js
export const prerender = false;
const CLIENT_ID = import.meta.env.CLIENT_ID;
const CLIENT_SECRET = import.meta.env.CLIENT_SECRET;
const REFRESH_TOKEN = import.meta.env.REFRESH_TOKEN;
const basic = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString("base64");
const NOW_PLAYING_ENDPOINT =
"https://api.spotify.com/v1/me/player/currently-playing";
const TOKEN_ENDPOINT = "https://accounts.spotify.com/api/token";
const getAccessToken = async () => {
const response = await fetch(TOKEN_ENDPOINT, {
method: "POST",
headers: {
Authorization: `Basic ${basic}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "refresh_token",
refresh_token: REFRESH_TOKEN,
}),
});
return response.json();
};
const getNowPlaying = async () => {
const { access_token } = await getAccessToken();
return fetch(NOW_PLAYING_ENDPOINT, {
headers: {
Authorization: `Bearer ${access_token}`,
},
});
};
export async function GET() {
const response = await getNowPlaying();
if (response.status === 204 || response.status > 400) {
return new Response(null, { status: 204 });
}
const song = await response.json();
if (!song.item) {
return new Response(null, { status: 204 });
}
const isPlaying = song.is_playing;
const title = song.item.name;
const artist = song.item.artists.map((_artist) => _artist.name).join(", ");
const album = song.item.album.name;
const albumArt = song.item.album.images[0]?.url;
const trackUrl = song.item.external_urls.spotify;
const progress = song.progress_ms
? Math.floor((song.progress_ms / song.item.duration_ms) * 100)
: 0;
return new Response(
JSON.stringify({
isPlaying,
title,
artist,
album,
albumArt,
trackUrl,
progress,
}),
{
status: 200,
headers: {
"Content-Type": "application/json",
"Cache-Control": "public, s-maxage=60, stale-while-revalidate=30",
},
}
);
}

View File

@ -1,36 +0,0 @@
---
import Layout from "../layouts/Layout.astro";
import Intro from "../components/Intro.astro";
//import Projects from "../components/Projects.astro";
import Posts from "../components/Posts.astro";
import WaveDivider from "../components/WaveDivider.astro";
//import Webring from "../components/Webring.astro";
//import SpotifyNowPlaying from "../components/SpotifyNowPlaying.astro";
import Socials from "../components/Socials.astro";
import BlogList from "../components/BlogList.astro"; // Import the new component
// TODO: Fill in your preferences.
const variables = {
name: "Kristian Emil Takvam",
subtitles:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent lobortis nisi ante, nec tincidunt ligula mattis nec. Maecenas metus mauris, fermentum et vulputate ut, dapibus vel massa.",
};
---
<Layout title={variables.name}>
<main>
<Intro name={variables.name} subtitle={variables.subtitles} />
<WaveDivider color="rosewater" speed={100} size={0.8} direction="left" />
<!--
<Posts />
<WaveDivider color="teal" speed={100} size={0.8} direction="left" />
-->
<BlogList /> <!-- Use the new component -->
<Socials />
</main>
</Layout>

View File

@ -1,123 +0,0 @@
---
import { getCollection, type CollectionEntry } from "astro:content";
import Layout from "../../layouts/Layout.astro";
import Intro from "../../components/Intro.astro";
import WaveDivider from "../../components/WaveDivider.astro";
import Socials from "../../components/Socials.astro";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
interface Props {
post: CollectionEntry<"blog">;
}
const { post } = Astro.props;
const { title, description, date } = post.data;
const { Content } = await post.render();
---
<Layout title={title}>
<Intro name={title} subtitle={description ?? ""} />
<WaveDivider color="lavender" />
<section class="post">
<div class="content">
<p class="post-date">{date.toDateString()}</p>
<article class="post-body">
<Content />
</article>
</div>
</section>
<WaveDivider color="lavender" direction="right" />
<Socials />
</Layout>
<style>
.post {
padding: 2rem 2rem 4rem;
display: flex;
justify-content: center;
}
.content {
max-width: 800px;
width: 100%;
}
.post-date {
color: var(--ctp-subtext0);
font-size: 0.9rem;
opacity: 0.7;
margin-bottom: 2rem;
text-align: center;
}
.post-body {
color: var(--ctp-text);
line-height: 1.7;
font-size: 1.05rem;
}
/* Style markdown content, matching Posts.astro */
.post-body :global(p) {
margin-bottom: 1.2rem;
}
.post-body :global(h1),
.post-body :global(h2),
.post-body :global(h3) {
margin-top: 2rem;
margin-bottom: 1rem;
color: var(--ctp-lavender);
}
.post-body :global(a) {
color: var(--ctp-pink);
}
.post-body :global(ul),
.post-body :global(ol) {
margin-bottom: 1.2rem;
padding-left: 1.5rem;
}
.post-body :global(blockquote) {
border-left: 3px solid var(--ctp-lavender);
padding-left: 1rem;
margin: 1.5rem 0;
color: var(--ctp-subtext0);
font-style: italic;
}
.post-body :global(code) {
background-color: var(--ctp-mantle);
padding: 0.2rem 0.4rem;
border-radius: 4px;
font-size: 0.9em;
}
.post-body :global(pre) {
background-color: var(--ctp-mantle);
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
margin-bottom: 1.2rem;
}
.post-body :global(pre code) {
background: none;
padding: 0;
}
.post-body :global(img) {
max-width: 100%;
border-radius: 8px;
margin: 1.5rem 0;
}
@media (max-width: 600px) {
.post {
padding: 1.5rem 1rem 3rem;
}
.post-body {
font-size: 1rem;
}
}
</style>

View File

@ -1,42 +0,0 @@
---
import Layout from "../layouts/Layout.astro";
import Intro from "../components/Intro.astro";
import Projects from "../components/Projects.astro";
import Posts from "../components/Posts.astro";
import WaveDivider from "../components/WaveDivider.astro";
import Webring from "../components/Webring.astro";
import SpotifyNowPlaying from "../components/SpotifyNowPlaying.astro";
import Socials from "../components/Socials.astro";
import Blogs from "../components/Blogs.astro";
// TODO: Fill in your preferences.
const variables = {
name: "Kristian Emil Takvam",
subtitles:
"This is my blog where I share my thoughts on programming, technology, and life in general. Stay tuned for updates!",
};
---
<Layout title={variables.name}>
<main>
<Intro name={variables.name} subtitle={variables.subtitles} />
<WaveDivider color="rosewater" speed={100} size={0.8} direction="left" />
<Blogs />
<WaveDivider color="teal" speed={100} size={0.8} direction="left" />
<Projects />
<WaveDivider color="flamingo" speed={100} size={0.8} direction="right" />
<SpotifyNowPlaying />
<WaveDivider color="mauve" speed={100} size={0.8} direction="left" />
<!--<Webring />
<WaveDivider color="pink" speed={100} size={0.8} direction="right" />
-->
<Socials />
</main>
<footer style="text-align: center;">
<p>&copy; 2025 Kristian Emil Takvam | Built with the <a href="https://github.com/trueberryless-org/astro-portfolio-template" target="_blank">Astro-portfolio-template</a> theme by <a href="https://trueberryless.org/" target="_blank">@trueberryless</a></p>
</footer>
</Layout>

View File

@ -1,9 +0,0 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"],
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}