diff --git a/README.md b/README.md index beeec02..5799d7b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ # [PKRM.DEV](https://pkrm.dev) -This is the repo for my personal website ([pkrm.dev](https://pkrm.dev)). Feel free to fork this project or download the code and use it for your needs. Happy coding! +This is the repo for my personal website ([pkrm.dev](https://pkrm.dev)). + +Heavily inspired by the "Hello Friend NG" HUGO Theme, found [here](https://github.com/rhazdon/hugo-theme-hello-friend-ng). + +Feel free to fork this project or download the code and use it for your needs. Happy coding! diff --git a/app/static/bg.png b/app/static/bg.png deleted file mode 100644 index 5d338cd..0000000 Binary files a/app/static/bg.png and /dev/null differ diff --git a/app/static/github.png b/app/static/github.png new file mode 100644 index 0000000..3cdff93 Binary files /dev/null and b/app/static/github.png differ diff --git a/app/static/gnugpg.png b/app/static/gnugpg.png new file mode 100644 index 0000000..6d772a6 Binary files /dev/null and b/app/static/gnugpg.png differ diff --git a/app/static/gnupg.png b/app/static/gnupg.png new file mode 100644 index 0000000..7efc415 Binary files /dev/null and b/app/static/gnupg.png differ diff --git a/app/static/index.css b/app/static/index.css deleted file mode 100644 index fa3d332..0000000 --- a/app/static/index.css +++ /dev/null @@ -1,451 +0,0 @@ -* { - font-family: 'Kanit', sans-serif; - margin: 0; - scroll-behavior: smooth; -} - -body{ - overflow-x: hidden; - background-image: url(/static/bg.png); - background-size: cover; - color: #fff; - will-change: transform; -} - -.fa-angle-down { - color: #fff; - font-size: 1.823vw; - display: flex; - justify-content: center; - align-items: center; - position: absolute; - bottom: 5.208vw; -} - -.fa-angle-down:hover { - opacity: .6; - cursor: pointer; -} - -/* Fixed footer */ -footer { - position: sticky; - bottom: 0; - background-color: #0d0d0d; - font-size: 1.042vw; - display: flex; - justify-content: center; - align-items: center; - z-index: 10; - padding: 1.042vw; -} - -footer a { - text-decoration: underline; - color: white -} - -footer a:hover { - opacity: .6; - cursor: pointer; -} - -/* Media query for footer on tablets */ -@media screen and (max-width: 1280px) { - footer { - font-size: 2.5vw; - } -} - -/* Media query for footer on mobile */ -@media screen and (max-width: 600px) { - footer { - font-size: 5vw; - } -} - -/* Navbar mobile icons */ -#hamburger i { - font-size: 2.083vw; - position: absolute; - top: 40px; - right: 40px; - display: none; -} - -#x i { - font-size: 2.083vw; - position: absolute; - top: 40px; - right: 40px; - display: none; -} - - -/* Main page (Hi I'm Parker) */ -#main { - height: 100vh; - width: 100vw; - position: relative; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; -} - -nav { - display: flex; - justify-content: center; - align-items: center; -} - -nav a { - text-decoration: none; - color: #fff; - font-size: 1.823vw; - margin: 0 25px; -} - -nav a:hover { - opacity: .6; - cursor: pointer; -} - -.icons { - display: flex; - justify-content: center; - align-items: center; -} - -.icons i { - font-size: 3.125vw; - margin: 1.042vw 50px; -} - -.icons i:hover { - opacity: .6; - cursor: pointer; -} - -header { - text-align: center; - position: relative; - display: flex; - justify-content: center; - align-items: center; -} - -header h1 { - font-size: 8.333vw; -} - -header h2 { - font-size: 3.125vw; - /* animation: bringIn 2s; */ - padding-right: 50px; -} - -/* Main section media query for tablets */ -@media screen and (max-width: 1280px) { - nav a { - font-size: 4vw; - margin-bottom: 3.646vw; - } - - header h1 { - font-size: 12vw; - } - - header h2 { - font-size: 7vw; - padding-right: 25px; - } - - .icons { - margin-top: 3vw; - } - - .icons i { - font-size: 7vw; - margin: 0 25px; - } - - .fa-angle-down { - font-size: 5vw; - bottom: 15vw; - } -} - -/* Main section media query for mobile */ -@media screen and (max-width: 600px) { - #hamburger i, - #x i { - font-size: 8vw; - } - nav { - flex-direction: column; - position: absolute; - } - - nav a { - font-size: 7vw; - margin-bottom: 15vw; - } - - header { - flex-direction: column; - bottom: 100px; - } - - header h1 { - font-size: 17vw; - } - - header h2 { - font-size: 12vw; - padding-right: 0; - } - - .icons { - flex-direction: row; - position: absolute; - bottom: 60vw; - } - - .icons i { - font-size: 12vw; - margin: 0 5px; - } - - .fa-angle-down { - font-size: 8vw; - bottom: 20vw; - } -} - -/* Create the keyframes fade in */ -@keyframes fadeIn { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@-webkit-keyframes fadeIn { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -/* About me section */ -#about { - height: 100vh; - width: 100vw; - position: relative; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; -} - -#about h1 { - font-size: 4.167vw; - margin-bottom: 1.563vw; -} - -#about p { - font-size: 1.563vw; - width: 50%; - text-align: center; -} - -/* About section media query for tablets */ -@media screen and (max-width: 1280px) { - #about h1 { - font-size: 10vw; - } - #about p { - font-size: 4vw; - width: 80%; - } -} - -/* About section media query for mobile */ -@media screen and (max-width: 600px) { - #about h1 { - font-size: 12vw; - } - #about p { - font-size: 5vw; - width: 80%; - } -} - -/* Slider for Projects - Credit to this codepen - https://codepen.io/maheshambure21/pen/qZZrxy */ -*, *:before, *:after { - box-sizing: border-box; -} - -.slider { - height: 100vh; - position: relative; - overflow: hidden; - display: flex; - flex-flow: row nowrap; - align-items: flex-end; - justify-content: center; -} - -.slider__nav { - width: 1.042vw; - height: 1.042vw; - margin: 1.042vw 0.521vw; - border-radius: 50%; - z-index: 10; - outline: 14px solid white; - outline-offset: -14px; - cursor: pointer; - appearance: none; -} - -.slider__nav:checked { - -webkit-animation: check 0.4s linear forwards; - animation: check 0.4s linear forwards; -} - -.slider__nav:checked:nth-of-type(1) ~ .slider__inner { - left: 0%; -} - -.slider__nav:checked:nth-of-type(2) ~ .slider__inner { - left: -100%; -} - -.slider__nav:checked:nth-of-type(3) ~ .slider__inner { - left: -200%; -} - -.slider__nav:checked:nth-of-type(4) ~ .slider__inner { - left: -300%; -} - -.slider__inner { - position: absolute; - top: 0; - left: 0; - width: 400%; - height: 100%; - -webkit-transition: left 0.7s; - transition: left 0.7s; - display: flex; - flex-flow: row nowrap; -} - -.slider__contents { - height: 100%; - text-align: center; - display: flex; - flex: 1; - flex-flow: column nowrap; - align-items: center; - justify-content: center; -} - -.slider__caption { - font-size: 4.167vw; - margin: 1.563vw; - max-width: 75%; -} - -.slider__txt { - color: white; - max-width: 30%; - font-size: 1.563vw; -} - -.slider__txt .inner-reference { - color: white; - text-decoration: underline; -} - -.slider__button { - font-size: 1.563vw; - padding: 0.391vw 1.042vw; - border-radius: 5px; - background: #333; - color: white; - text-decoration: none; - cursor: pointer; - margin-right: 1.042vw; -} - -.slider__button:hover { - opacity: .6; - transition: all .2s ease-in-out; - -webkit-transition: all .2s ease-in-out; -} - -/* Projects section media query for tablets */ -@media screen and (max-width: 1280px) { - .slider__caption { - max-width: 95%; - font-size: 10vw; - } - .slider__txt { - font-size: 4vw; - max-width: 80%; - } - - .slider__button { - font-size: 4vw; - } - - .slider__nav { - margin-bottom: 2.64vw; - width: 3vw; - height: 3vw; - margin: 0 2vw 10vw 2vw; - } -} - -/* Projects section media query for mobile */ -@media screen and (max-width: 600px) { - .slider__caption { - font-size: 12vw; - max-width: 95%; - } - .slider__txt { - font-size: 5vw; - max-width: 80%; - } - - .slider__button { - font-size: 5vw; - display: flex; - justify-content: center; - margin: 0; - margin-bottom: 6vw; - } - - .slider__nav { - margin-bottom: 2.64vw; - width: 5vw; - height: 5vw; - margin: 0 2vw 10vw 2vw; - } -} - -@-webkit-keyframes check { - 50% { - outline-color: #333; - } - 100% { - outline-color: #333; - } -} - -@keyframes check { - 50% { - outline-color: #333; - } - 100% { - outline-color: #333; - } -} \ No newline at end of file diff --git a/app/static/index.js b/app/static/index.js deleted file mode 100644 index cad0481..0000000 --- a/app/static/index.js +++ /dev/null @@ -1,185 +0,0 @@ -// Define the variables -const hamburger = document.querySelector('.fa-bars'); -const x = document.querySelector('.fa-times'); -const nav = document.querySelectorAll('nav')[0]; -const navOptions = nav.querySelectorAll('a'); -const main = document.getElementById('main'); -const mainh1 = main.getElementsByTagName('h1')[0]; -const mainh2 = main.getElementsByTagName('h2')[0]; -const iconNav = document.querySelectorAll('nav')[1]; -const icons = document.querySelectorAll('nav')[1].getElementsByTagName('i'); -const arrow = document.getElementById('about-text') -const projects = document.getElementById('projects'); -const footer = document.querySelector('footer'); - -// If the user is on mobile, remove the fingerprint from the footer, also remove -// the down arrow buttons -if (window.innerWidth <= 768) { - footer.removeChild(footer.lastChild); - arrow.style.display = 'none'; -} - -// If the user is on mobile -if (window.innerWidth < 768) { - x.style.display = 'none'; - hamburger.style.display = 'block'; - nav.style.display = 'none'; - mobileAnimations(); -} else { - x.style.display = 'none'; - hamburger.style.display = 'none'; - nav.style.display = 'flex'; - desktopAnimations(); -} - -// Only create listener if the user is on mobile -if (window.innerWidth < 768) { - // When the hamburger is clicked, show the X and open the menu - hamburger.addEventListener('click', function () { - hamburger.style.display = 'none'; - x.style.display = 'block'; - mainh1.style.display = 'none'; - mainh2.style.display = 'none'; - iconNav.style.display = 'none'; - arrow.style.display = 'none'; - - // Slowly fade in the nav with keyframes - nav.style.display = 'flex'; - nav.style.animation = 'fadeIn 0.75s ease-in-out'; - - // Lock the scroll - document.body.style.overflow = 'hidden'; - }); -} - -// Collapse the mobile nav menu -function collapseMenu() { - hamburger.style.display = 'block'; - x.style.display = 'none'; - nav.style.display = 'none'; - - // Slowly fade in the h1, h2, icons, and arrow with keyframes - mainh1.style.display = 'block'; - mainh1.style.animation = 'fadeIn 0.75s ease-in-out'; - mainh2.style.display = 'block'; - mainh2.style.animation = 'fadeIn 0.75s ease-in-out'; - iconNav.style.display = 'flex'; - iconNav.style.animation = 'fadeIn 0.75s ease-in-out'; - arrow.style.display = 'block'; - arrow.style.animation = 'fadeIn 0.75s ease-in-out'; - - // Unlock the scroll - document.body.style.overflow = 'auto'; -} - -// Only create listener if the user is on mobile -if (window.innerWidth < 768) { - // When the X is clicked, show the hamburger and close the menu - x.addEventListener('click', function () { - collapseMenu(); - }); -} - -// When a nav link is clicked, close the menu -const navLinks = document.querySelectorAll('nav a'); -navLinks.forEach(function (link) { - link.addEventListener('click', function () { - // Only collapse the menu if the user is on mobile - if (window.innerWidth < 768) { - collapseMenu(); - } - }); -}); - -// Animation for the desktop version -function desktopAnimations() { - let everythingSlideUp = new mojs.Html({ - el: main, - y: {150: 0}, - duration: 1000, - delay: 250, - easing: 'sin.out' - }).play(); - - let everythingOpacity = new mojs.Html({ - el: main, - opacity: {0: 1}, - duration: 2000, - delay: 250, - easing: 'sin.out' - }).play(); -} - -// Animation for the mobile version -function mobileAnimations() { - let h2ScaleUp = new mojs.Html({ - el: mainh2, - y: {75: 75}, - opacity: {0: 1}, - scale: {0.5: 1}, - duration: 1500, - easing: mojs.easing.path('M0,100 C50,100 50,67.578125 50,50 C50,32.421875 50,0 100,0') - }).play(); - - let h2SlideUp = new mojs.Html({ - el: mainh2, - y: {75: 0}, - duration: 1500, - delay: 1000, - easing: mojs.easing.path('M0,100 C50,100 50,67.578125 50,50 C50,32.421875 50,0 100,0') - }).play(); - - let h1Opacity = new mojs.Html({ - el: mainh1, - opacity: {0: 1}, - duration: 2000, - delay: 1750, - easing: 'sin.out' - }).play(); - - let iconBringIn1 = new mojs.Html({ - el: icons[0], - y: {25: 0}, - opacity: {0: 1}, - duration: 1000, - delay: 2000, - easing: 'sin.out' - }).play(); - - let iconBringIn2 = new mojs.Html({ - el: icons[1], - y: {25: 0}, - opacity: {0: 1}, - duration: 1000, - delay: 2250, - easing: 'sin.out' - }).play(); -} - -// Rotate the projects every 4 seconds, only for desktop -window.onload = slideProjects(); -function slideProjects() { - const inputs = document.querySelectorAll('input'); - if (window.innerWidth >= 768) { - let i = 0; - setInterval(() => { - if (i == -1) { - return; - } - - inputs[i].checked = true; - i++; - - if (i >= inputs.length) { - i = 0; - } - }, 4000); - - // If one of the inputs is clicked, stop the rotation of the projects - inputs.forEach(input => { - input.addEventListener('click', () => { - i = -1; - }); - }); - } -} \ No newline at end of file diff --git a/app/static/linkedin.png b/app/static/linkedin.png new file mode 100644 index 0000000..f52d8a4 Binary files /dev/null and b/app/static/linkedin.png differ diff --git a/app/static/mail.png b/app/static/mail.png new file mode 100644 index 0000000..c300991 Binary files /dev/null and b/app/static/mail.png differ diff --git a/app/static/contact.asc b/app/static/parker.asc similarity index 100% rename from app/static/contact.asc rename to app/static/parker.asc diff --git a/app/templates/about.html b/app/templates/about.html new file mode 100644 index 0000000..63e79d7 --- /dev/null +++ b/app/templates/about.html @@ -0,0 +1,132 @@ + + + + + + Home + + + + +
+

About Me

+

I am a senior in high school who enjoys programming and learning more about different technologies. I manage a Debian home server where I self-host tools like: DNSCrypt, AdGuard, WireGuard, Syncthing, and many more media/system management utilities.

Find my work by viewing my open-sourced repositories on GitHub.

+
+ + + + + + \ No newline at end of file diff --git a/app/templates/contact.html b/app/templates/contact.html index 1bdd2b9..b312ab4 100644 --- a/app/templates/contact.html +++ b/app/templates/contact.html @@ -2,245 +2,269 @@ - - - - - Contact | pkrm.dev - - - - - - - - - - - - - - - - - - - + Home - Back Home + +
-

ATTENTION: To send any sensitive information, please email me at contact@pkrm.dev and encrypt the message with my PGP public key. This form should not be thought of as a secure way of communication.

-
- - +

Contact Me

+ + + + - +
+ {% if success %} -

Thank you for contacting me! I will get back to you soon.

- {% endif %} +

Thank you for contacting me. I'll get back soon.

+ {% endif %} {% if error %} -

There was an error sending your message. Please try again later.

+

An error occured, please try again later.

{% endif %}
+ + - - + \ No newline at end of file diff --git a/app/templates/index.html b/app/templates/index.html index 6dadecf..8da65fc 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -2,121 +2,164 @@ - - - - - - - Parker | pkrm.dev - - - - - - - - - - - - - - - - - - - + Home - -
- - - - - -
-

Hi, I'm

-

PARKER

-
- - - - -
- -
-

About Me

-

I am a Senior in high school and enjoy learning about new technologies. I currently use HTML/CSS, Python, Javascript, and SQL. I have competed at the district and state levels in SkillsUSA for Cybersecurity and Programming, and have placed 2nd for the Congressional App Challenge. This year I plan on learning more about web3 and artificial intelligence.

- - -
- -
-
- - - - -
-
-

PeakPass

-

- PeakPass is a password manager that also doubles as a tool to check your passwords against those that have been affected in previous data breaches. Along with this we offer a blog to teach users about standards that keep them safe online. -
-
- Source Code - View Site -

-
-
-

Aqua Bot

-

- A multipurpose Discord bot made with the discord.py 2.0 library. Aqua Bot has features like moderation, an economy, gambling. In addition to this, users can play music from YouTube, Spotify, and SoundCloud thanks to lavalink.py -
-
- Source Code -

-
-
-

VaultCheck

-

- Uses the bitwarden-cli tool, the Twilio API, and the HaveIBeenPwned API in order to check your vault for leaked passwords. If a compromised password is found, it alerts you with a text message. -
-
- Source Code -

-
-
-

Messagearr

-

- Docker container that has integration with Radarr in order to allow users to request movies to be downloaded through text messaging. Currently supports the Twilio and Telnyx messaging APIs. -
-
- Source Code - Docker Hub -

-
-
+
- - + + + +
+

Hello, I'm Parker

+

A student with a strong passion for technology and privacy.

+ + + + + +
+ + - + \ No newline at end of file diff --git a/app/templates/pgp.html b/app/templates/pgp.html new file mode 100644 index 0000000..6d67cca --- /dev/null +++ b/app/templates/pgp.html @@ -0,0 +1,169 @@ + + + + + + Home + + + + +
+

Copy my key below, or click here to download it.

+

+ + -----BEGIN PGP PUBLIC KEY BLOCK----- +

+ xjMEZI06YRYJKwYBBAHaRw8BAQdAxymP7jguJxjtKKqGQ/fSXGwZVzOiix6iRS1F + 6BVMu+3NG1BhcmtlciBNIDxjb250YWN0QHBrcm0uZGV2PsKTBBMWCgA7FiEEWLdr + i7q4eU0h4leclc0uDH4ynyoFAmSNOmECGwMFCwkIBwICIgIGFQoJCAsCBBYCAwEC + HgcCF4AACgkQlc0uDH4ynyrBIAEAu7y2oebvsBb+tJXPUOZkjqE+rsAwiDgHLj3U + gYMM4XUBALPsZ4IgA5mWhTDTV00QLHmVtybCJzCdc7LzyvQH78cHzjgEZI06YRIK + KwYBBAGXVQEFAQEHQLBpSX+qSOtSFVrp9+VfJGHsoPaIhoxIjz44byrtLXZ4AwEI + B8J4BBgWCgAgFiEEWLdri7q4eU0h4leclc0uDH4ynyoFAmSNOmECGwwACgkQlc0u + DH4ynyqQhAEAuo1HGXEKkBUzji+cCW3wF/oqg0cQklQzfKUkifLhiC8A/2gdilxS + AYHKY0lEJandkOjid/otDdiIZCUBt5mXjncL + =ni8o +
+ -----END PGP PUBLIC KEY BLOCK----- + +

+
+ + + + + + + + \ No newline at end of file diff --git a/app/views.py b/app/views.py index 98f25ac..937bcb8 100644 --- a/app/views.py +++ b/app/views.py @@ -4,7 +4,6 @@ import discord import dotenv app = flask.Flask(__name__) -app.secret_key = os.urandom(32) dotenv.load_dotenv() webhook_url = os.getenv("WEBHOOK_URL") @@ -12,6 +11,10 @@ webhook_url = os.getenv("WEBHOOK_URL") def index(): return flask.render_template('index.html') +@app.route('/about', methods=['GET']) +def about(): + return flask.render_template('about.html') + @app.route('/contact', methods=['GET', 'POST']) def contact(): if flask.request.method == 'GET': @@ -35,4 +38,13 @@ def contact(): return flask.render_template('contact.html', success=True) # If any error happens for any reason, return the contact page with error except: - return flask.render_template('contact.html', error=True) \ No newline at end of file + return flask.render_template('contact.html', error=True) + +@app.route('/pgp', methods=['GET']) +def pgp(): + return flask.render_template('pgp.html') + +@app.route('/parker.asc', methods=['GET']) +def parker(): + # Send the file to download + return flask.send_file('static/parker.asc', as_attachment=True) \ No newline at end of file