feat: switch to nextjs (#7)

* feat: switch to nextjs

* chore: move everyting to main dir

* fix: blogpostgen

* chore: dot?

* chore: remove blogposts

* fix: everything

* chore: why

* chore: move to public

* chore: fetch

* chore: remove slash

* chore: aedfa

* feat: defenitive nextjs move
This commit is contained in:
2023-11-17 19:29:30 +01:00
committed by GitHub
parent fd1f6c9f15
commit da0982b5ff
50 changed files with 2928 additions and 1985 deletions

View File

@@ -1,14 +0,0 @@
module.exports = {
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': 'warn',
},
}

3
.eslintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}

55
.gitignore vendored
View File

@@ -1,29 +1,38 @@
# Logs
logs
*.log
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# local env files
.env*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# vercel
.vercel
# various stuff
blogPosts.json
public/blog/*.xml
public/blog/feed.json
# typescript
*.tsbuildinfo
next-env.d.ts
blogPosts.json

5
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

7
.idea/discord.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

12
.idea/mainwebsite.iml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/mainwebsite.iml" filepath="$PROJECT_DIR$/.idea/mainwebsite.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"javascript.preferences.importModuleSpecifierEnding": "minimal"
}

View File

@@ -2,6 +2,6 @@
My public face on the wild internet.
Hosted on Vercel. Made with React, Typescript, Markdown and Material UI.
Hosted on Vercel. Made with Next.js, Typescript, Markdown and Material UI.
URL: https://srizan.dev

View File

@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/pfp.webp" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sr Izan's front page for the web:tm:</title>
<script async src="https://analytics.srizan.dev/ua.js" data-website-id="54ccb44c-b03c-4790-8262-3e1a82241a24"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

2
next.config.js Normal file
View File

@@ -0,0 +1,2 @@
/** @type {import('next').NextConfig} */
export const nextConfig = {}

View File

@@ -1,52 +1,38 @@
{
"name": "mainwebsite",
"name": "njs-move",
"version": "0.1.0",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "node src/blogPostGenerator.js && vite",
"build": "node src/blogPostGenerator.js && tsc && vite build",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
"dev": "node src/blogPostGenerator.js && next dev",
"build": "next build",
"start": "node src/blogPostGenerator.js;next start",
"lint": "next lint"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-brands-svg-icons": "^6.4.0",
"@fortawesome/free-regular-svg-icons": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@mui/icons-material": "^5.14.12",
"@mui/material": "^5.14.5",
"dayjs": "^1.11.9",
"@mui/material": "^5.14.18",
"dayjs": "^1.11.10",
"feed": "^4.2.2",
"glob": "^10.3.3",
"glob": "^10.3.10",
"gray-matter": "^4.0.3",
"marked": "^8.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"react-markdown": "^8.0.7",
"react-router-dom": "^6.15.0",
"marked": "^10.0.0",
"next": "^14.0.3",
"react": "^18",
"react-dom": "^18",
"react-icons": "^4.12.0",
"react-markdown": "^9.0.1",
"react-syntax-highlighter": "^15.5.0",
"remark-gfm": "^3.0.1"
"remark-gfm": "^4.0.0"
},
"devDependencies": {
"@types/js-yaml": "^4.0.5",
"@types/mdx": "^2.0.6",
"@types/node": "^20.5.1",
"@types/react": "^18.0.37",
"@types/react-dom": "^18.0.11",
"@types/react-helmet": "^6.1.9",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/react-syntax-highlighter": "^15.5.10",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"@vitejs/plugin-react": "^4.0.0",
"eslint": "^8.38.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"typescript": "^5.0.2",
"vite": "^4.3.9"
"eslint": "^8",
"eslint-config-next": "14.0.2",
"typescript": "^5"
}
}

198
public/blog/atom.xml Normal file
View File

@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>https://srizan.dev/blog</id>
<title>Sr Izan's Blog</title>
<updated>2023-11-17T18:19:59.603Z</updated>
<generator>https://github.com/jpmonette/feed</generator>
<author>
<name>Sr Izan</name>
<email>izan@srizan.dev</email>
<uri>https://srizan.dev</uri>
</author>
<link rel="alternate" href="https://srizan.dev/blog"/>
<link rel="self" href="https://srizan.dev/blog/atom.xml"/>
<subtitle>My little donowall place on the net</subtitle>
<logo>https://srizan.dev/pfp.png</logo>
<icon>https://srizan.dev/pfp.png</icon>
<rights>Copyleft 2023, Sr Izan</rights>
<entry>
<title type="html"><![CDATA[My tales of MongoDB migration]]></title>
<id>https://srizan.dev/blog/2</id>
<link href="https://srizan.dev/blog/2"/>
<updated>2023-11-11T23:00:00.000Z</updated>
<summary type="html"><![CDATA[Here I ramble about the last service migration I did, MongoDB, and all the difficulties that came with it.]]></summary>
<content type="html"><![CDATA[<h2>Introduction</h2>
<p>So, the last few months I&#39;ve been migrating services from my good old Raspberry Pi into my new HP server and the last service I migrated was MongoDB.</p>
<p>I&#39;ve been using MongoDB for a while now and I&#39;ve been using it for a few things, like my discord bots, <a href="https://github.com/SrIzan10/webhooks-ui">webhooks-ui</a> and probably other projects I don&#39;t remember right now.</p>
<p>So, let&#39;s get started!</p>
<h2>Testing the plan</h2>
<p>My database instance is on Docker with a replica set of 1 node (itself) so <a href="https://www.prisma.io/">Prisma</a> works.</p>
<p>My idea is to add the HP server as a secondary replica and then promote it to be the primary one, but I don&#39;t know if that will work, so we need to test some stuff.</p>
<p>I first created 2 docker containers on my <a href="https://gist.github.com/SrIzan10/50bc2ba689a4cc43bcbac2799cc733c9">main Ryzen machine</a>&#39;s WSL Ubuntu instance.</p>
<p>I created a <code>docker-compose.yml</code> file with the following content:</p>
<pre><code class="language-yml">version: &quot;3.8&quot;
services:
mongo1:
image: mongo:4.4.17-rc0-focal
container_name: mongo1
restart: always
ports:
- 27017:27017
volumes:
- ./mongo1:/data/db
command: mongod --replSet mongoset
networks:
- mongo
mongo2:
image: mongo:4.4.17-rc0-focal
container_name: mongo2
restart: always
ports:
- 27018:27017
volumes:
- ./mongo2:/data/db
command: mongod --replSet mongoset
networks:
- mongo
networks:
mongo:
</code></pre>
<p>and ran it with <code>docker compose up -d</code>.</p>
<p>I went to connect with MongoDB Compass and it didn&#39;t work for some reason. I asked GPT and nothing. It looks like it accepted the connection but it won&#39;t connect, so I installed <code>mongosh</code> and tried to connect with that.</p>
<pre><code class="language-bash">$ mongosh mongodb://localhost:27017
</code></pre>
<p>...and it worked! That didn&#39;t make any sense, but okay, we can work with it.</p>
<p>I then connected to the <code>mongo1</code> instance and ran the following commands:</p>
<pre><code class="language-bash">&gt; rs.initiate()
</code></pre>
<p>and it worked, but only that same database connected. Before adding the second database to the replica, I went ahead and pinged it from the first container (just to check if the network configuration worked):</p>
<pre><code class="language-bash">docker exec mongo1 sh -c &quot;rm /bin/ping;apt update;apt install inetutils-ping -y;ping mongo2&quot;
</code></pre>
<p>I removed /bin/ping because I tried to transfer the binary from WSL to the container but it still needed some libraries and I didn&#39;t want to bother, so I just installed the package.</p>
<p>It worked, so I went ahead and added the second database to the replica set:</p>
<pre><code class="language-bash">&gt; rs.add(&quot;mongo2&quot;)
</code></pre>
<p>After waiting for it, the second database connected and everything was working fine. Let&#39;s create a collection and some documents on the primary replica (mongo1):</p>
<pre><code class="language-bash">&gt; use test
&gt; db.createCollection(&quot;test&quot;)
&gt; db.test.insertOne({ name: &quot;test&quot; })
</code></pre>
<p>and then, let&#39;s check if it&#39;s on the second replica (mongo2):</p>
<pre><code class="language-bash">$ mongosh mongodb://localhost:27017
</code></pre>
<pre><code class="language-bash">&gt; use test
&gt; db.getMongo().setReadPref(&quot;secondaryPreferred&quot;)
&gt; db.test.find()
</code></pre>
<p>and, yeah, that worked.</p>
<p>I don&#39;t really know if ORMs will read when connecting to the second replica, but for now it&#39;s fine as the main plan is on track.<br>So, to promote I connected to the primary replica (mongo1) and ran the following command:</p>
<pre><code class="language-bash">&gt; rs.stepDown()
</code></pre>
<p>And that worked! Woo! The second replica is now the primary one. We can now start <em>drum rolls please</em>:</p>
<h2>The migration</h2>
<p>This is it. We&#39;re doing it.</p>
<p>I went ahead and created a new docker-compose file on my server with the following content:</p>
<pre><code class="language-yml">version: &quot;3.8&quot;
services:
mongo:
image: mongo:4.4.17-rc0-focal
container_name: mongodb
restart: unless-stopped
ports:
- 27017:27017
volumes:
- ./mongo:/data/db
command: mongod --replSet rs0
</code></pre>
<p>After deploying the stack, I connected using mongosh to the primary db and ran the following command:</p>
<pre><code class="language-bash">&gt; rs.add(&quot;ip&quot;)
</code></pre>
<p>and after waiting for a while it looked like it worked. I then connected to the new database and ran the following command to check if the replica cloned fine:</p>
<pre><code class="language-bash">&gt; db.getMongo().setReadPref(&quot;secondaryPreferred&quot;)
</code></pre>
<p>and let&#39;s just let the results speak for themselves:</p>
<pre><code class="language-bash">rs0 [direct: secondary] test&gt; show dbs
# author&#39;s note: some dbs are redacted for privacy reasons
admin 80.00 KiB
api 80.00 KiB
ava 40.00 KiB
bask 168.00 KiB
config 144.00 KiB
local 348.00 KiB
vinci 428.00 KiB
rs0 [direct: secondary] test&gt; use vinci
switched to db vinci
rs0 [direct: secondary] vinci&gt; show tables
afk
birthdays
chatgpt
giveaways-enters
giveaways-message
padyama
suggestions
twitter
warns
youtube
rs0 [direct: secondary] vinci&gt; db.afk.find()
[
{
_id: ObjectId(&quot;sadfsad fsadfsdf&quot;),
id: &#39;redacted&#39;,
reason: &#39;redacted&#39;,
__v: 0
},
{
_id: ObjectId(&quot;asdfsadfadf&quot;),
id: &#39;redacted&#39;,
reason: &#39;readacted&#39;,
__v: 0
}
]
rs0 [direct: secondary] vinci&gt;
</code></pre>
<p>Nice. let&#39;s now try to write something to the database from Vinci:<br><img src="https://img.srizan.dev/Discord_a2iXkWYxwn.png" alt=""><br>That just worked and we can see it on the secondary replica:</p>
<pre><code class="language-bash">rs0 [direct: secondary] vinci&gt; db.afk.find({ id: &#39;703974042700611634&#39; })
[
{
_id: ObjectId(&quot;6550eccc6154a8c9030fe76a&quot;),
id: &#39;703974042700611634&#39;,
reason: &#39;test&#39;,
__v: 0
}
]
</code></pre>
<p>Let&#39;s now edit all .envs and change the database url to the new secondary one. For this I checked all dbs that I have and then go from top to bottom editing the secrets.</p>
<p>After that was done I needed to deploy all changes. I went ahead and created too many tabs on my terminal and ran the all deployment commands on each tab. At the same time.<br>I really hope that doesn&#39;t make my server run out of ram, because I&#39;m really short on that.</p>
<p>After executing all the commands I <code>rs.stepDown()</code>&#39;ed the primary Raspberry Pi replica and, as expected, the HP Server took over.</p>
<p>The last command of the day:</p>
<pre><code class="language-bash">&gt; rs.remove(&quot;ip&quot;)
</code></pre>
<p>...SIKE! I needed to check the logs of the containers to see if everything was working fine. The <code>api</code> and <code>vinci</code> to be exact.<br>This is because <code>api</code> runs Prisma and <code>vinci</code> runs the now defunct in my stack, <a href="https://mongoosejs.com/">mongoose</a>.</p>
<p>Luckily enough, both were fine, so I was free. Yay!</p>
<h2>Conclusion</h2>
<p>Welp, that was a lot of work. I&#39;m glad it&#39;s over. I got my HP server on July and it&#39;s now November and I just finished migrating.<br>Could I have done it in less time? Yes.<br>Was I lazy? Also yes.</p>
<p>So that answers all your questions.</p>
<p>I hope you enjoyed this my first blog post, and thankfully it was a big one.<br>This took 3 hours in total, but at the end of the day, it was worth it.</p>
<p>I&#39;ll see you in the next one!</p>
]]></content>
<author>
<name>Sr Izan</name>
<uri>https://srizan.dev</uri>
</author>
</entry>
<entry>
<title type="html"><![CDATA[Welcome to my new blog!]]></title>
<id>https://srizan.dev/blog/1</id>
<link href="https://srizan.dev/blog/1"/>
<updated>2023-08-19T22:00:00.000Z</updated>
<summary type="html"><![CDATA[This post welcomes you to my new blog]]></summary>
<content type="html"><![CDATA[<h1>Hey!</h1>
<p>This is probably the last time I&#39;m going to make a blog. I&#39;ve made a few in the past, but I&#39;ve never really stuck to them. I&#39;m hoping that this time will be different.<br>This one was made entirely from scratch using React and Markdown, initially trying to use MDX, but it was a pain to set up, and it didn&#39;t end up working in the end.<br>I&#39;m hoping to post about my projects, and maybe some other stuff too. I&#39;m not sure yet, but I&#39;ll figure it out as I go along.<br>Anyways, thank you for reading. I hope you enjoyed my UX/UI for this one!</p>
<p>PD: I need some help for making the blog text look good and readable, so hit me up on my Discord if you have any ideas.</p>
]]></content>
<author>
<name>Sr Izan</name>
<uri>https://srizan.dev</uri>
</author>
</entry>
</feed>

38
public/blog/feed.json Normal file

File diff suppressed because one or more lines are too long

191
public/blog/rss.xml Normal file
View File

@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Sr Izan's Blog</title>
<link>https://srizan.dev/blog</link>
<description>My little donowall place on the net</description>
<lastBuildDate>Fri, 17 Nov 2023 18:19:59 GMT</lastBuildDate>
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
<generator>https://github.com/jpmonette/feed</generator>
<language>en</language>
<image>
<title>Sr Izan's Blog</title>
<url>https://srizan.dev/pfp.png</url>
<link>https://srizan.dev/blog</link>
</image>
<copyright>Copyleft 2023, Sr Izan</copyright>
<atom:link href="https://srizan.dev/blog/rss.xml" rel="self" type="application/rss+xml"/>
<item>
<title><![CDATA[My tales of MongoDB migration]]></title>
<link>https://srizan.dev/blog/2</link>
<guid>https://srizan.dev/blog/2</guid>
<pubDate>Sat, 11 Nov 2023 23:00:00 GMT</pubDate>
<description><![CDATA[Here I ramble about the last service migration I did, MongoDB, and all the difficulties that came with it.]]></description>
<content:encoded><![CDATA[<h2>Introduction</h2>
<p>So, the last few months I&#39;ve been migrating services from my good old Raspberry Pi into my new HP server and the last service I migrated was MongoDB.</p>
<p>I&#39;ve been using MongoDB for a while now and I&#39;ve been using it for a few things, like my discord bots, <a href="https://github.com/SrIzan10/webhooks-ui">webhooks-ui</a> and probably other projects I don&#39;t remember right now.</p>
<p>So, let&#39;s get started!</p>
<h2>Testing the plan</h2>
<p>My database instance is on Docker with a replica set of 1 node (itself) so <a href="https://www.prisma.io/">Prisma</a> works.</p>
<p>My idea is to add the HP server as a secondary replica and then promote it to be the primary one, but I don&#39;t know if that will work, so we need to test some stuff.</p>
<p>I first created 2 docker containers on my <a href="https://gist.github.com/SrIzan10/50bc2ba689a4cc43bcbac2799cc733c9">main Ryzen machine</a>&#39;s WSL Ubuntu instance.</p>
<p>I created a <code>docker-compose.yml</code> file with the following content:</p>
<pre><code class="language-yml">version: &quot;3.8&quot;
services:
mongo1:
image: mongo:4.4.17-rc0-focal
container_name: mongo1
restart: always
ports:
- 27017:27017
volumes:
- ./mongo1:/data/db
command: mongod --replSet mongoset
networks:
- mongo
mongo2:
image: mongo:4.4.17-rc0-focal
container_name: mongo2
restart: always
ports:
- 27018:27017
volumes:
- ./mongo2:/data/db
command: mongod --replSet mongoset
networks:
- mongo
networks:
mongo:
</code></pre>
<p>and ran it with <code>docker compose up -d</code>.</p>
<p>I went to connect with MongoDB Compass and it didn&#39;t work for some reason. I asked GPT and nothing. It looks like it accepted the connection but it won&#39;t connect, so I installed <code>mongosh</code> and tried to connect with that.</p>
<pre><code class="language-bash">$ mongosh mongodb://localhost:27017
</code></pre>
<p>...and it worked! That didn&#39;t make any sense, but okay, we can work with it.</p>
<p>I then connected to the <code>mongo1</code> instance and ran the following commands:</p>
<pre><code class="language-bash">&gt; rs.initiate()
</code></pre>
<p>and it worked, but only that same database connected. Before adding the second database to the replica, I went ahead and pinged it from the first container (just to check if the network configuration worked):</p>
<pre><code class="language-bash">docker exec mongo1 sh -c &quot;rm /bin/ping;apt update;apt install inetutils-ping -y;ping mongo2&quot;
</code></pre>
<p>I removed /bin/ping because I tried to transfer the binary from WSL to the container but it still needed some libraries and I didn&#39;t want to bother, so I just installed the package.</p>
<p>It worked, so I went ahead and added the second database to the replica set:</p>
<pre><code class="language-bash">&gt; rs.add(&quot;mongo2&quot;)
</code></pre>
<p>After waiting for it, the second database connected and everything was working fine. Let&#39;s create a collection and some documents on the primary replica (mongo1):</p>
<pre><code class="language-bash">&gt; use test
&gt; db.createCollection(&quot;test&quot;)
&gt; db.test.insertOne({ name: &quot;test&quot; })
</code></pre>
<p>and then, let&#39;s check if it&#39;s on the second replica (mongo2):</p>
<pre><code class="language-bash">$ mongosh mongodb://localhost:27017
</code></pre>
<pre><code class="language-bash">&gt; use test
&gt; db.getMongo().setReadPref(&quot;secondaryPreferred&quot;)
&gt; db.test.find()
</code></pre>
<p>and, yeah, that worked.</p>
<p>I don&#39;t really know if ORMs will read when connecting to the second replica, but for now it&#39;s fine as the main plan is on track.<br>So, to promote I connected to the primary replica (mongo1) and ran the following command:</p>
<pre><code class="language-bash">&gt; rs.stepDown()
</code></pre>
<p>And that worked! Woo! The second replica is now the primary one. We can now start <em>drum rolls please</em>:</p>
<h2>The migration</h2>
<p>This is it. We&#39;re doing it.</p>
<p>I went ahead and created a new docker-compose file on my server with the following content:</p>
<pre><code class="language-yml">version: &quot;3.8&quot;
services:
mongo:
image: mongo:4.4.17-rc0-focal
container_name: mongodb
restart: unless-stopped
ports:
- 27017:27017
volumes:
- ./mongo:/data/db
command: mongod --replSet rs0
</code></pre>
<p>After deploying the stack, I connected using mongosh to the primary db and ran the following command:</p>
<pre><code class="language-bash">&gt; rs.add(&quot;ip&quot;)
</code></pre>
<p>and after waiting for a while it looked like it worked. I then connected to the new database and ran the following command to check if the replica cloned fine:</p>
<pre><code class="language-bash">&gt; db.getMongo().setReadPref(&quot;secondaryPreferred&quot;)
</code></pre>
<p>and let&#39;s just let the results speak for themselves:</p>
<pre><code class="language-bash">rs0 [direct: secondary] test&gt; show dbs
# author&#39;s note: some dbs are redacted for privacy reasons
admin 80.00 KiB
api 80.00 KiB
ava 40.00 KiB
bask 168.00 KiB
config 144.00 KiB
local 348.00 KiB
vinci 428.00 KiB
rs0 [direct: secondary] test&gt; use vinci
switched to db vinci
rs0 [direct: secondary] vinci&gt; show tables
afk
birthdays
chatgpt
giveaways-enters
giveaways-message
padyama
suggestions
twitter
warns
youtube
rs0 [direct: secondary] vinci&gt; db.afk.find()
[
{
_id: ObjectId(&quot;sadfsad fsadfsdf&quot;),
id: &#39;redacted&#39;,
reason: &#39;redacted&#39;,
__v: 0
},
{
_id: ObjectId(&quot;asdfsadfadf&quot;),
id: &#39;redacted&#39;,
reason: &#39;readacted&#39;,
__v: 0
}
]
rs0 [direct: secondary] vinci&gt;
</code></pre>
<p>Nice. let&#39;s now try to write something to the database from Vinci:<br><img src="https://img.srizan.dev/Discord_a2iXkWYxwn.png" alt=""><br>That just worked and we can see it on the secondary replica:</p>
<pre><code class="language-bash">rs0 [direct: secondary] vinci&gt; db.afk.find({ id: &#39;703974042700611634&#39; })
[
{
_id: ObjectId(&quot;6550eccc6154a8c9030fe76a&quot;),
id: &#39;703974042700611634&#39;,
reason: &#39;test&#39;,
__v: 0
}
]
</code></pre>
<p>Let&#39;s now edit all .envs and change the database url to the new secondary one. For this I checked all dbs that I have and then go from top to bottom editing the secrets.</p>
<p>After that was done I needed to deploy all changes. I went ahead and created too many tabs on my terminal and ran the all deployment commands on each tab. At the same time.<br>I really hope that doesn&#39;t make my server run out of ram, because I&#39;m really short on that.</p>
<p>After executing all the commands I <code>rs.stepDown()</code>&#39;ed the primary Raspberry Pi replica and, as expected, the HP Server took over.</p>
<p>The last command of the day:</p>
<pre><code class="language-bash">&gt; rs.remove(&quot;ip&quot;)
</code></pre>
<p>...SIKE! I needed to check the logs of the containers to see if everything was working fine. The <code>api</code> and <code>vinci</code> to be exact.<br>This is because <code>api</code> runs Prisma and <code>vinci</code> runs the now defunct in my stack, <a href="https://mongoosejs.com/">mongoose</a>.</p>
<p>Luckily enough, both were fine, so I was free. Yay!</p>
<h2>Conclusion</h2>
<p>Welp, that was a lot of work. I&#39;m glad it&#39;s over. I got my HP server on July and it&#39;s now November and I just finished migrating.<br>Could I have done it in less time? Yes.<br>Was I lazy? Also yes.</p>
<p>So that answers all your questions.</p>
<p>I hope you enjoyed this my first blog post, and thankfully it was a big one.<br>This took 3 hours in total, but at the end of the day, it was worth it.</p>
<p>I&#39;ll see you in the next one!</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[Welcome to my new blog!]]></title>
<link>https://srizan.dev/blog/1</link>
<guid>https://srizan.dev/blog/1</guid>
<pubDate>Sat, 19 Aug 2023 22:00:00 GMT</pubDate>
<description><![CDATA[This post welcomes you to my new blog]]></description>
<content:encoded><![CDATA[<h1>Hey!</h1>
<p>This is probably the last time I&#39;m going to make a blog. I&#39;ve made a few in the past, but I&#39;ve never really stuck to them. I&#39;m hoping that this time will be different.<br>This one was made entirely from scratch using React and Markdown, initially trying to use MDX, but it was a pain to set up, and it didn&#39;t end up working in the end.<br>I&#39;m hoping to post about my projects, and maybe some other stuff too. I&#39;m not sure yet, but I&#39;ll figure it out as I go along.<br>Anyways, thank you for reading. I hope you enjoyed my UX/UI for this one!</p>
<p>PD: I need some help for making the blog text look good and readable, so hit me up on my Discord if you have any ideas.</p>
]]></content:encoded>
</item>
</channel>
</rss>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="31.88" height="32" aria-hidden="true" class="iconify iconify--logos" preserveAspectRatio="xMidYMid meet" role="img" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"/><stop offset="100%" stop-color="#BD34FE"/></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"/><stop offset="8.333%" stop-color="#FFDD35"/><stop offset="100%" stop-color="#FFA800"/></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"/><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,27 @@
import '../../_css/Root.css';
import React from 'react';
import { SiOsu } from 'react-icons/si';
import { FaDiscord, FaGithub, FaMastodon, FaTwitter, FaBlog } from 'react-icons/fa6';
import Link from "next/link";
import Image from 'next/image';
export default function Page() {
return (
<div>
<div className='aboutMeBox'>
{/* style={{ borderRadius: '70px' }} */}
<Link href='/collab'><Image src='/pfp.webp' alt='main profile picture' width='200' height='200' /></Link>
<p>A spanish hobbyist developer and osu! player</p>
<p>Stalk me on social media:</p>
<div className='icons'>
<Link href='https://github.com/SrIzan10'><FaGithub /></Link>
<Link href='/blog'><FaBlog /></Link>
<Link href='https://discord.com/users/703974042700611634'><FaDiscord /></Link>
<Link href='https://social.srizan.dev'><FaMastodon /></Link>
<Link href='https://twitter.com/itssrizan'><FaTwitter /></Link>
<Link href='https://osu.ppy.sh/users/25350735'><SiOsu /></Link>
</div>
</div>
</div>
)
}

View File

@@ -1,47 +1,36 @@
import { useParams } from "react-router-dom";
import { Helmet } from "react-helmet";
import { useEffect, useState } from "react";
import Head from "next/head";
import * as fs from 'node:fs/promises'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
import { BlogNavBar } from "./BlogNavBar.tsx";
import '../css/BlogPost.css';
import BlogNavBar from "../../../_components/BlogNavBar";
import '../../../_css/BlogPost.css';
import React from "react";
import jsonDataArray from '../../../../../public/blogPosts.json';
import { redirect } from "next/navigation";
export function BlogPost() {
const id = Number(useParams().id);
if (isNaN(id)) {
// if it's not a number, redirect to the blog page
window.location.href = '/blog';
}
const [jsonData, setJsonData] = useState<BlogPostJSONResponse>({
export default async function Page({ params }: { params: { id: string } }) {
const id = parseInt(params.id);
if (Number.isNaN(id)) redirect('/blog')
let jsonData = {
id: 0,
title: '',
description: '',
date: '',
fileName: '',
fileContent: ''
});
}
useEffect(() => {
const fetchData = async () => {
const jsonFetch = await import('../../blogPosts.json');
const jsonDataArray = jsonFetch.default;
const filteredPost = jsonDataArray.filter((post) => post.id === id)[0];
if (filteredPost) {
setJsonData(filteredPost);
} else {
document.location.href = '/blog';
}
};
fetchData();
}, [id]);
const filteredPost = jsonDataArray.filter((post) => post.id === id)[0];
if (filteredPost) {
jsonData = filteredPost;
} else {
redirect('/blog')
}
return (
<div>
<Helmet>
<Head>
<title>{jsonData.title}</title>
<meta name="description" content={jsonData.description} />
<meta name="og:title" content={jsonData.title} />
@@ -49,21 +38,19 @@ export function BlogPost() {
<meta name="og:type" content="article" />
<meta name="og:url" content={`https://srizan.dev/blog/${jsonData.id}`} />
<meta name="og:article:author" content="Sr Izan" />
</Helmet>
</Head>
<BlogNavBar title={jsonData.title} />
<div className={'blogPostContent'}>
<ReactMarkdown remarkPlugins={[remarkGfm]} components={{
code(props) {
const { children, className, ...rest } = props
code({node, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '')
return match ? (
<SyntaxHighlighter
{...rest}
style={atomDark}
customStyle={{ backgroundColor: '#171717', outline: 'solid' }}
codeTagProps={{ className: 'codeHighlighter' }}
language={match[1]}
PreTag="div"
// eslint-disable-next-line react/no-children-prop
children={String(children).replace(/\n$/, '')}
/>
) : (
@@ -77,6 +64,7 @@ export function BlogPost() {
)
},
img(props) {
// eslint-disable-next-line jsx-a11y/alt-text
return <img {...props} style={{ maxWidth: '100%' }} />
}
}}>

View File

@@ -0,0 +1,30 @@
import '../../../app/_css/Blog.css';
import Head from 'next/head';
import blogPosts from '../../../../public/blogPosts.json'
import BlogPostCard from '../../../app/_components/BlogPostCard';
import BlogNavBar from '../../../app/_components/BlogNavBar';
import BlogRssDial from '@/app/_components/BlogRssDial';
function Blog() {
return (
<div>
<Head>
<title>Blog</title>
<meta name="theme-color" content="#0d0d0d" />
</Head>
<BlogNavBar />
<div className="blogPosts">
{blogPosts.map((post) => {
return (
<BlogPostCard {...post} key={post.id} />
);
})}
</div>
<div className="bottomRight">
<BlogRssDial />
</div>
</div>
);
}
export default Blog;

View File

@@ -1,7 +1,9 @@
import Image from "next/image";
export default function Collab() {
return (
<div>
<img src="/collab.webp" useMap="#image-map" />
<Image src="/collab.webp" useMap="#image-map" alt="Collab image" />
<map name="image-map">
<area target="_blank" alt="Sr Izan" title="Sr Izan" href="https://srizan.dev" coords="0,0,280,316" shape="rect" />

View File

@@ -1,8 +1,13 @@
import { useEffect, useState } from 'react';
import '../css/BlogNavBar.css'
import { Link } from 'react-router-dom';
// sadge
'use client';
export function BlogNavBar(props: Props) {
import { useEffect, useState } from 'react';
import '../_css/BlogNavBar.css'
import Link from 'next/link';
import Pfp from '../../../public/pfp.webp';
import Image from 'next/image';
export default function BlogNavBar(props: Props) {
const [isScrolled, setIsScrolled] = useState(false);
useEffect(() => {
@@ -26,7 +31,7 @@ export function BlogNavBar(props: Props) {
<img src="/pfp.webp" alt="main profile picture" height="50vh" />
<p>{props.title || 'Sr Izan\'s blog'}</p>
</div>
<Link to={props.title ? '/blog' : '/'} className="backHomeLink">Go back {props.title ? 'to posts' : 'home'}</Link>
<Link href={props.title ? '/blog' : '/'} className="backHomeLink">Go back {props.title ? 'to posts' : 'home'}</Link>
</div>
)
}

View File

@@ -1,12 +1,14 @@
"use client"
import Box from '@mui/material/Box';
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography';
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat.js'
import '../css/BlogPostCard.css'
import '../_css/BlogPostCard.css'
import { Button, CardActions } from "@mui/material";
import {Link} from "react-router-dom";
import Link from "next/link";
dayjs.extend(customParseFormat)
export default function BlogPostCard(props: Props) {
@@ -25,7 +27,7 @@ export default function BlogPostCard(props: Props) {
</Typography>
</CardContent>
<CardActions className={'actions'}>
<Link to={`/blog/${props.id}`}><Button size="small">Read</Button></Link>
<Link href={`/blog/${props.id}`}><Button size="small">Read</Button></Link>
</CardActions>
</Box>
</Card>

View File

@@ -0,0 +1,44 @@
'use client'
import SpeedDial from "@mui/material/SpeedDial";
import SpeedDialAction from "@mui/material/SpeedDialAction";
import { FaRss, FaAtom } from "react-icons/fa6";
import { MdDataObject } from 'react-icons/md'
const actions = [
{ icon: <FaRss />, name: 'RSS' },
{ icon: <MdDataObject />, name: 'JSON' },
{ icon: <FaAtom />, name: 'Atom' }
];
export default function BlogRssDial() {
const handleChange = (event: string) => {
switch (event) {
case 'RSS':
window.location.href = '/blog/rss.xml'
break;
case 'JSON':
window.location.href = '/blog/feed.json'
break;
case 'Atom':
window.location.href = '/blog/atom.xml'
break;
}
}
return (
<SpeedDial
ariaLabel="SpeedDial basic example"
sx={{ position: 'absolute', bottom: 16, right: 16 }}
icon={<FaRss />}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
onClick={() => handleChange(action.name)}
/>
))}
</SpeedDial>
)
}

View File

@@ -0,0 +1,56 @@
"use client";
import { CacheProvider } from "@emotion/react";
import createCache from "@emotion/cache";
import { useServerInsertedHTML } from "next/navigation";
import { ReactNode, useState } from "react";
import { ThemeProvider } from "@mui/material/styles";
import theme from "./theme";
export function RootStyleRegistry({
children,
}: {
children: ReactNode;
}) {
const [{ cache, flush }] = useState(() => {
const cache = createCache({ key: "my" });
cache.compat = true;
const prevInsert = cache.insert;
let inserted: string[] = [];
cache.insert = (...args) => {
const serialized = args[1];
if (cache.inserted[serialized.name] === undefined) {
inserted.push(serialized.name);
}
return prevInsert(...args);
};
const flush = () => {
const prevInserted = inserted;
inserted = [];
return prevInserted;
};
return { cache, flush };
});
useServerInsertedHTML(() => {
const names = flush();
if (names.length === 0) return null;
let styles = "";
for (const name of names) {
styles += cache.inserted[name];
}
return (
<style
data-emotion={`${cache.key} ${names.join(" ")}`}
dangerouslySetInnerHTML={{
__html: styles,
}}
/>
);
});
return (
<CacheProvider value={cache}>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</CacheProvider>
);
}

View File

@@ -0,0 +1,36 @@
import { Roboto } from 'next/font/google';
import { createTheme } from '@mui/material/styles';
const roboto = Roboto({
weight: ['300', '400', '500', '700'],
subsets: ['latin'],
display: 'swap',
});
// Check if window is defined before accessing its properties
const prefersDarkMode = typeof window !== 'undefined' ? window.matchMedia('(prefers-color-scheme: dark)') : null;
// Add event listener only if prefersDarkMode is defined
if (prefersDarkMode) {
prefersDarkMode.addEventListener('change', () => {
location.reload();
});
}
const theme = createTheme({
palette: {
mode: prefersDarkMode && prefersDarkMode.matches ? 'dark' : 'light',
background: {
default: prefersDarkMode && prefersDarkMode.matches ? '#0d0d0d' : '#fafafa',
paper: prefersDarkMode && prefersDarkMode.matches ? '#0d0d0d' : '#fafafa',
},
primary: {
main: '#646cff',
},
},
typography: {
fontFamily: roboto.style.fontFamily,
},
});
export default theme;

View File

@@ -7,16 +7,18 @@
line-height: 2;
}
code {
font-family: 'JetBrains Mono', monospace;
}
.codeHighlighter {
font-family: 'JetBrains Mono', monospace;
shadow: 0;
code .codeHighlighter {
font-family: var(--font-mono);
}
@media (max-width: 900px) {
.blogPostContent {
padding: 0;
}
}
@media (prefers-color-scheme: light) {
.codeHighlighter {
background-color: #FFF;
}
}

View File

@@ -1,7 +1,6 @@
.aboutMeBox {
width: 480px;
height: 360px;
position: absolute;
top: 50%;
left: 50%;
@@ -17,6 +16,11 @@
.icons * {
margin-right: 20px;
}
.icons svg {
/* change from 1em */
width: 1.5em;
height: 1.5em;
}
.icons *:last-child {
margin-right: 0;
@@ -26,4 +30,4 @@
.aboutMeBox {
width: 100%;
}
}
}

View File

@@ -13,6 +13,9 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
--font-mono: ui-monospace, 'JetBrains Mono', Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
}
a {

28
src/app/layout.tsx Normal file
View File

@@ -0,0 +1,28 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import { RootStyleRegistry } from './_components/ThemeRegistry/EmotionRootStyleRegistry'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Sr Izan\'s corner for the net',
icons: { icon: '/pfp.webp' }
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>
<RootStyleRegistry>
{children}
</RootStyleRegistry>
</body>
</html>
)
}

3
src/blog/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

8
src/blog/.idea/blog.iml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="EMPTY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

7
src/blog/.idea/discord.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

8
src/blog/.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/blog.iml" filepath="$PROJECT_DIR$/.idea/blog.iml" />
</modules>
</component>
</project>

6
src/blog/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View File

@@ -57,7 +57,7 @@ await glob('./src/blog/**/*.md').then(async (files) => {
}
})
fs.writeFileSync('./blogPosts.json', JSON.stringify(data))
fs.writeFileSync('./public/blogPosts.json', JSON.stringify(data))
fs.writeFileSync('./public/blog/feed.json', feed.json1())
fs.writeFileSync('./public/blog/rss.xml', feed.rss2())
fs.writeFileSync('./public/blog/atom.xml', feed.atom1())

View File

@@ -1,84 +0,0 @@
import React from 'react';
import MuiAlert, { AlertProps } from "@mui/material/Alert";
import Snackbar from "@mui/material/Snackbar";
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import CloseIcon from '@mui/icons-material/Close';
import Modal from '@mui/material/Modal';
import Box from '@mui/material/Box';
import Typography from "@mui/material/Typography";
const modalStyle = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
const Alert = React.forwardRef<HTMLDivElement, AlertProps>(function Alert(
props,
ref,
) {
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
});
export default function AnalyticsNotice() {
const [open, setOpen] = React.useState(window.localStorage.getItem('analyticsNotice') !== 'false');
const [modalOpen, setModalOpen] = React.useState(false);
const handleModalOpen = () => setModalOpen(true);
const handleClose = (_event?: React.SyntheticEvent | Event, reason?: string) => {
if (reason === 'clickaway') {
return;
}
setOpen(false);
setModalOpen(false);
window.localStorage.setItem('analyticsNotice', 'false');
};
const action = (
<React.Fragment>
<Button color="secondary" size="small" onClick={handleModalOpen} sx={{ color: 'white' }}>
WAIT WHAT?
</Button>
<IconButton
size="small"
aria-label="close"
color="inherit"
onClick={handleClose}
>
<CloseIcon fontSize="small" sx={{ color: 'white' }}/>
</IconButton>
</React.Fragment>
);
return (
<div>
<Snackbar open={open} onClose={handleClose} action={action}>
<Alert severity="info" action={action}>hi this website uses <a href='https://umami.is' style={{ color: "white" }}><u>umami</u></a> for analytics</Alert>
</Snackbar>
<Modal
open={modalOpen}
onClose={() => handleClose()}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={modalStyle}>
<Typography id="modal-modal-title" variant="h6" component="h2">
Analytics
</Typography>
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
Umami is used to track page visits. These aren't sold to anyone and are just to see what you guys like.
Endpoint is https://analytics.srizan.dev
</Typography>
</Box>
</Modal>
</div>
)
}

View File

@@ -1,53 +0,0 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './pages/App.tsx'
import './css/index.css'
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { ThemeProvider, createTheme } from '@mui/material/styles';
import Blog from "./pages/Blog.tsx";
import { BlogPost } from "./components/BlogPost.tsx";
import AnalyticsNotice from "./components/AnalyticsNotice.tsx";
import Collab from './pages/Collab.tsx';
const router = createBrowserRouter([
{
path: "/",
element: <App />,
},
{
path: "/blog",
element: <Blog />,
},
{
path: "/blog/:id",
element: <BlogPost />
},
{
path: '/collab',
element: <Collab />
}
]);
const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)');
const darkTheme = createTheme({
palette: {
mode: prefersDarkMode.matches ? 'dark' : 'light',
background: {
default: prefersDarkMode.matches ? '#0d0d0d' : '#fafafa',
paper: prefersDarkMode.matches ? '#0d0d0d' : '#fafafa',
}
},
});
prefersDarkMode.addEventListener('change', () => {
location.reload()
});
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<ThemeProvider theme={darkTheme}>
<AnalyticsNotice />
<RouterProvider router={router} />
</ThemeProvider>
</React.StrictMode>,
)

View File

@@ -1,30 +0,0 @@
import '../css/App.css'
import React from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faDiscord, faGithub, faMastodon, faTwitter } from '@fortawesome/free-brands-svg-icons'
import { faBlog, faCircle } from '@fortawesome/free-solid-svg-icons'
import { Link } from "react-router-dom";
function App() {
const [osuBeat, setOsuBeat] = React.useState(false)
return (
<div>
<div className='aboutMeBox'>
{/* style={{ borderRadius: '70px' }} */}
<Link to='/collab'><img src='/pfp.webp' alt='main profile picture' height='200px' /></Link>
<p>I'm a hobbyist developer and osu! player based on Spain who loves to open-source and to work on teams.</p>
<p>Stalk me on social media:</p>
<div className='icons'>
<a href='https://github.com/SrIzan10'><FontAwesomeIcon icon={faGithub} /></a>
<Link to='/blog'><FontAwesomeIcon icon={faBlog} /></Link>
<a href='https://discord.com/users/703974042700611634'><FontAwesomeIcon icon={faDiscord} /></a>
<a href='https://social.srizan.dev'><FontAwesomeIcon icon={faMastodon} /></a>
<a href='https://twitter.com/itssrizan'><FontAwesomeIcon icon={faTwitter} /></a>
<a href='https://osu.ppy.sh/users/25350735'><FontAwesomeIcon icon={faCircle} onMouseEnter={() => setOsuBeat(true)} onMouseLeave={() => setOsuBeat(false)} beatFade={osuBeat} /></a>
</div>
</div>
</div>
)
}
export default App

View File

@@ -1,66 +0,0 @@
import '../css/Blog.css';
import { Helmet } from 'react-helmet';
import blogPosts from '../../blogPosts.json'
import BlogPostCard from "../components/BlogPostCard.tsx";
import { BlogNavBar } from "../components/BlogNavBar.tsx";
import { faRss, faAtom } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import SpeedDial from '@mui/material/SpeedDial';
import SpeedDialAction from '@mui/material/SpeedDialAction';
import DataObject from "@mui/icons-material/DataObject";
const actions = [
{ icon: <FontAwesomeIcon icon={faRss} />, name: 'RSS' },
{ icon: <DataObject />, name: 'JSON' },
{ icon: <FontAwesomeIcon icon={faAtom} />, name: 'Atom' }
];
function Blog() {
const handleChange = (event: string) => {
switch (event) {
case 'RSS':
window.location.href = '/blog/rss.xml'
break;
case 'JSON':
window.location.href = '/blog/feed.json'
break;
case 'Atom':
window.location.href = '/blog/atom.xml'
break;
}
}
return (
<div>
<Helmet>
<title>Blog | Sr Izan's website</title>
<meta name="theme-color" content="#0d0d0d" />
</Helmet>
<BlogNavBar />
<div className="blogPosts">
{blogPosts.map((post) => {
return (
<BlogPostCard {...post} />
);
})}
</div>
<div className="bottomRight">
<SpeedDial
ariaLabel="SpeedDial basic example"
sx={{ position: 'absolute', bottom: 16, right: 16 }}
icon={<FontAwesomeIcon icon={faRss} />}
>
{actions.map((action) => (
<SpeedDialAction
key={action.name}
icon={action.icon}
tooltipTitle={action.name}
onClick={() => handleChange(action.name)}
/>
))}
</SpeedDial>
</div>
</div>
);
}
export default Blog;

1
src/vite-env.d.ts vendored
View File

@@ -1 +0,0 @@
/// <reference types="vite/client" />

View File

@@ -1,26 +1,27 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
/* Bundler mode */
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"types": ["vite/client"]
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src", "src/**/*.d.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}

View File

@@ -1,10 +0,0 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -1,5 +0,0 @@
{
"rewrites": [
{"source": "/(.*)", "destination": "/"}
]
}

View File

@@ -1,10 +0,0 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
port: 3000
}
})

3635
yarn.lock

File diff suppressed because it is too large Load Diff