Bunch of updates
24
.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Nuxt dev/build outputs
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.nuxt
|
||||||
|
.nitro
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
.fleet
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Local env files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
79
content/blog/Build-a-Keyboard-Links.md
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
title: Build a Keyboard Links
|
||||||
|
tags:
|
||||||
|
- keyboard
|
||||||
|
categories:
|
||||||
|
- builds
|
||||||
|
date: 2023-01-11 19:48:00
|
||||||
|
---
|
||||||
|
|
||||||
|
Trying to build your own keyboard? Here are some links!
|
||||||
|
|
||||||
|
## Keyboard builds
|
||||||
|
|
||||||
|
List of open source, ergonomic keyboards
|
||||||
|
https://github.com/Ultrahalf/ergo-keeb
|
||||||
|
|
||||||
|
Keyboard builders digest - Great site for news and inspiration
|
||||||
|
https://kbd.news/
|
||||||
|
|
||||||
|
## Shopping for parts
|
||||||
|
|
||||||
|
Little Keyboards - Low Cost boards with kits and low cost cases.
|
||||||
|
https://www.littlekeyboards.com/
|
||||||
|
|
||||||
|
Kriscable - In Europe but also has cool cables
|
||||||
|
https://kriscables.com/
|
||||||
|
|
||||||
|
Keebio - A little more expensive but offers pre-soldered boards for easier entry
|
||||||
|
https://keeb.io/
|
||||||
|
|
||||||
|
Insane ergo keyboards
|
||||||
|
https://bastardkb.com/
|
||||||
|
|
||||||
|
https://shop.beekeeb.com/
|
||||||
|
|
||||||
|
https://novelkeys.com/
|
||||||
|
|
||||||
|
https://mysticmechs.com/
|
||||||
|
|
||||||
|
https://boardsource.xyz/
|
||||||
|
|
||||||
|
Affordable Switches
|
||||||
|
https://divinikey.com/collections/switches
|
||||||
|
https://bolsakeyboardsupply.com/collections/all
|
||||||
|
https://en.akkogear.com/store/switch/
|
||||||
|
https://www.kailh.net/
|
||||||
|
|
||||||
|
##### High Quality key Caps
|
||||||
|
|
||||||
|
KBDFANS - https://kbdfans.com/collections/keycaps?filter.v.availability=1&filter.v.price.gte=&filter.v.price.lte=52&sort_by=created-descending
|
||||||
|
Keebmonkey - https://www.keebmonkey.com/collections/keycaps
|
||||||
|
KPREPUBLIC - https://kprepublic.com/collections/keycaps
|
||||||
|
|
||||||
|
## Firmware and setup
|
||||||
|
|
||||||
|
QMK Configurator - Firmware modification and compilation in your browser
|
||||||
|
https://config.qmk.fm/#/lily58/rev1/LAYOUT
|
||||||
|
|
||||||
|
Via - Keyboard Configuration in browser
|
||||||
|
https://usevia.app/#/
|
||||||
|
|
||||||
|
## My Builds
|
||||||
|
|
||||||
|
[Lily58 Pro](https://www.littlekeyboards.com/collections/lily58-pcb-kits/products/lily58-pro-pcb-kit)
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-6.png)
|
||||||
|
|
||||||
|
[Quefrency Rev. 3](https://keeb.io/collections/quefrency-split-staggered-65-keyboard/products/quefrency-60-65-split-staggered-keyboard-1)
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-7.png)
|
||||||
|
|
||||||
|
Spare parts numpad.
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-8.png)
|
||||||
|
|
||||||
|
Quefrency with green LEDs and spare keycaps
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-10.png)
|
||||||
|
|
||||||
|
Another Quefrency! This one is for a friends birthday. Fun cat keycaps. The tape is to explain what the cat keys are before first use.
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-17.png)
|
||||||
|
|
||||||
|
Why am I building keyboards like this? -> https://www.youtube.com/watch?v=76eALNFp3kk
|
17
content/blog/Catch-missing-image-assets-inside-image-tag.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: Catch missing image assets inside image tag
|
||||||
|
tags: []
|
||||||
|
categories:
|
||||||
|
- Web Dev
|
||||||
|
date: 2023-01-01 05:30:01
|
||||||
|
---
|
||||||
|
|
||||||
|
If an image is being displayed on a website and for some reason that asset disappears, you can catch that error and display a placeholder image with a little inline js.
|
||||||
|
|
||||||
|
Here is an example:
|
||||||
|
|
||||||
|
<img src="/marketing/importantImage.png"
|
||||||
|
onerror=" this.onerror = null; this.src='/marketing/backupimage.png';"
|
||||||
|
/>
|
||||||
|
|
||||||
|
This will help prevent image 404's on the site if someone decides to go and delete a bunch of images. Since is just a little js snippet, you can change the class, report the error or even remove the element entirely.
|
27
content/blog/Change-remote-origin-in-git-repo.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
title: Change remote origin in git repo
|
||||||
|
author: Max Gialanella
|
||||||
|
date: 2023-03-02 01:58:28
|
||||||
|
tags:
|
||||||
|
---
|
||||||
|
|
||||||
|
Sometimes you need to change the remote origin in a git repo, if the server moves or if you just get better at NGINX and change the URL to something cleaner. Here are the simple steps on how to update your remote origin.
|
||||||
|
|
||||||
|
##### List remote origins
|
||||||
|
|
||||||
|
`git remote -v`
|
||||||
|
|
||||||
|
##### Add new remote origin
|
||||||
|
|
||||||
|
`git remote set-url add origin https://sweetNewDomain/git/user/RepoName`
|
||||||
|
|
||||||
|
##### Remove old origin
|
||||||
|
|
||||||
|
`git remote set-url delete origin 192.168.1.33:3030/git/user/RepoName`
|
||||||
|
|
||||||
|
##### List remote origins again
|
||||||
|
|
||||||
|
`git remote -v`
|
||||||
|
|
||||||
|
Verify that your URLs are correct and do a `git fetch` make sure everything is working. On your next push, you will need to re-enter your username and password.
|
||||||
|
Nice work!
|
24
content/blog/Killing-programs-in-mac-or-linux.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
title: Killing programs in mac or linux
|
||||||
|
tags:
|
||||||
|
- linux
|
||||||
|
- bash
|
||||||
|
categories: []
|
||||||
|
date: 2023-01-01 05:30:35
|
||||||
|
---
|
||||||
|
|
||||||
|
To kill all instances of an application us the command **killall**
|
||||||
|
|
||||||
|
It can be tedious to find all the processes you are trying to kill based on process id. There is a cool little command that can do the work for you, killall.
|
||||||
|
|
||||||
|
You can kill all instances of a misbehaving program:
|
||||||
|
|
||||||
|
> $sudo killall discord
|
||||||
|
|
||||||
|
Or you can kill using wild cards:
|
||||||
|
|
||||||
|
> $sudo killall node\*
|
||||||
|
|
||||||
|
If you want to check what you will kill you can use the command:
|
||||||
|
|
||||||
|
> $ps aux | grep node\*
|
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
title: Linux Search text in this and all sub directories
|
||||||
|
author: Max Gialanella
|
||||||
|
tags:
|
||||||
|
- linux
|
||||||
|
- bash
|
||||||
|
categories: []
|
||||||
|
date: 2023-01-11 21:43:00
|
||||||
|
---
|
||||||
|
|
||||||
|
Search text files in current directory and all sub directories. Its super fast so don't worry if you have a node_modules directory or something.
|
||||||
|
|
||||||
|
Use this command:
|
||||||
|
`grep -rnw '.' -e 'search text'`
|
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: Lower Pipewire CPU usage on Ubuntu while using Firefox
|
||||||
|
author: Max Gialanella
|
||||||
|
date: 2023-06-14 16:50:45
|
||||||
|
tags:
|
||||||
|
---
|
||||||
|
|
||||||
|
I was noticing high CPU usage for the pipewire process on Ubunutu.
|
||||||
|
|
||||||
|
After some digging, I came across [this thread](https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1968). The culprit is an accessibility feature in Firefox. If you are not using firefox's speech synthases features you can disable it to drop CPU usage.
|
||||||
|
|
||||||
|
1. Type `about:config` into the Address bar.
|
||||||
|
1. Search `media.webspeech.synth.enabled`
|
||||||
|
1. Set `media.webspeech.synth.enabled` to false.
|
||||||
|
1. Restart Firefox and check pipwire process cpu usage
|
14
content/blog/Neovim.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
title: Neovim
|
||||||
|
author: Max Gialanella
|
||||||
|
tags:
|
||||||
|
- vim
|
||||||
|
categories:
|
||||||
|
- linux
|
||||||
|
date: 2023-01-01 16:57:00
|
||||||
|
---
|
||||||
|
|
||||||
|
Why would anyone in their right mind us vim? I asked myself this question 543 times in the last 3 years. To my own surprise, I found myself wanting to use vim. The justification being that you can write code without using a mouse.
|
||||||
|
|
||||||
|
Jumpstart Neovim
|
||||||
|
https://github.com/ur4ltz/kickstart.nvim
|
@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
title: Sunshine a Parsec Alternative for Linux, GeForce Now alternative for Windows
|
||||||
|
tags: []
|
||||||
|
categories: []
|
||||||
|
date: 2023-01-01 05:31:17
|
||||||
|
---
|
||||||
|
|
||||||
|
Sunshine is a desktop streaming client for linux that offers efficient, low latency PC streaming, for free.
|
||||||
|
Download Sunshine onto your linux machine (the host)
|
||||||
|
[Sunshine Github][1]
|
||||||
|
Download moonlight onto whatever device you streaming on (the client)
|
||||||
|
[Moonlight Homepage][2]
|
||||||
|
|
||||||
|
I have spent a considerable amount of time looking for something that would replace Parsec when I switched to linux. A number of posts spoke about NoMachine, TightVNC and a number of other VNC clients. None of them were sufficient for what I wanted; low latency, high refresh rate, unlimited access to my PC.
|
||||||
|
|
||||||
|
Sunshine checks all the boxes. It uses an implementation of Nvidia's GameStream service. Its really fast and reliable. Better yet, you don't need to install Nvidia's crappy GeForce experience if you are doing this on a windows machine, you can also use Sunshine.
|
||||||
|
|
||||||
|
If you want to use sunshine outside of your local network, turn on Upnp in your router so that sunshine can set up all the required ports.
|
||||||
|
|
||||||
|
Checkout the sunshine docs for installation instructions -> https://docs.lizardbyte.dev/projects/sunshine/en/latest/about/installation.html
|
||||||
|
|
||||||
|
Start Running
|
||||||
|
cd downloads
|
||||||
|
./sunshine.AppImage --install && ./sunshine.AppImage
|
||||||
|
|
||||||
|
Once its set up, you can configure options in a browser. Visit:
|
||||||
|
https://localhost:47990/
|
||||||
|
|
||||||
|
[1]: https://github.com/LizardByte/Sunshine
|
||||||
|
[2]: https://moonlight-stream.org/
|
||||||
|
|
||||||
|
Additional fun stuff:
|
||||||
|
Moodlight supports wake on lan WOL. This is a feature on motherboards that allows the computer to boot up or wake from sleep.
|
||||||
|
Go into your bios and make sure its turned on. You can tell your eithernet controller is running during sleep if you sleep your computer but you can still see the orange light blinking on your eithernet port.
|
||||||
|
If you setup moonlight to work outside your network, you can also setup Wake on Lan, to wake up your computer if you are out of the house.
|
||||||
|
Port Forward UDP 7-9 to the Sunshine host. Now you can wake your computer from anywhere in the world.
|
41
content/blog/Proudest-software-engineering-achievements.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
title: "Proudest Software Engineering Achievements"
|
||||||
|
description: "A few highlights of my time programming"
|
||||||
|
date: "2023-12-1"
|
||||||
|
---
|
||||||
|
|
||||||
|
### Mitigating hype-driven-development as a team lead. Building a cohesive tech stack and uniform product
|
||||||
|
|
||||||
|
Migrating from an old, unsupported technology to a new, feature rich technology is often the crux of a companies future proofing strategy. Being left on an aging platform could hobble future growth and slow development.
|
||||||
|
|
||||||
|
When I was team lead at Article One Partners, this was the first thing I wanted to tackle. How do we migrate an antiquated, fragmented system, to a more cohesive stack? A previous dev, convinced the manager to adopt new technologies as they became popular. This left us with a LAMP stack, running Smarty (an old PHP frontend) jQuery UI, Angular, React and Vue, with two weird support microservices written in Node.js and a nightmare webpack config. All this was built on top of an old Zend 2 backend with a partially implemented ORM on an aging version of PHP.
|
||||||
|
|
||||||
|
We needed a clever strategy to mitigate tech debt, remove unused technologies, update to new technologies, support old features that could not be updated, all while allowing for development of new features.
|
||||||
|
|
||||||
|
The first order of business was to plan a path forward with the technologies that were giving us the greatest benefit. For the front end it was Vue, with a custom webpack config. Which required the phasing out of the React, Angular and jQuery. For the backend we planned a migration path, removing all handwritten MySQL and MySQL stored procedures, migrating to the latest version of Doctrine ORM and then migrating the entire stack from PHP 5 to PHP 7.
|
||||||
|
|
||||||
|
The first step was to build a uniform data layer between the backend and the frontend, this allowed all technologies to exist at the same time using the same data. Pieces of the frontend and backend could then be replaced piecemeal without disrupting the current application.
|
||||||
|
|
||||||
|
We continued:
|
||||||
|
|
||||||
|
- Isolating Features per page with a uniform data delivery for entire site.
|
||||||
|
- Removing dependencies on old pages that used Smarty, Angular & React.
|
||||||
|
- Building Interoperable components for legacy pages and vue pages.
|
||||||
|
- Replacing dated pages, as time allowed, with single page applications.
|
||||||
|
|
||||||
|
As time went on, the efforts and planning paid off. The entire application was using a uniform frontend and styles framework. Each page was an isolated single page application which could be maintained and updated easily. The backed was secure and much faster thanks to PHP 7. The whole stack was maintainable. Dependencies and packages were at their latest versions.
|
||||||
|
|
||||||
|
This is one of my proudest achievements because of the scale and foresight put into the project was a massive success. The tech stack became much more secure, faster and
|
||||||
|
maintainable, new features could be developed and uniform technologies across the platform allowed for very fancy new projects to be built and implemented with minimal hassle.
|
||||||
|
|
||||||
|
(More in progress)
|
||||||
|
|
||||||
|
### building a performant browser based pdf annotator
|
||||||
|
|
||||||
|
### integration of socket.io backend and vue event-bus for solid scribe
|
||||||
|
|
||||||
|
### analytical engine for finding study submission duplicates
|
||||||
|
|
||||||
|
### dynamic programming for satisfaction criteria in submissions highlights
|
||||||
|
|
||||||
|
### cross implementation of smarty and vue for migration
|
24
content/blog/Run-bash-script-on-linux-start.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
title: Run bash script on linux start
|
||||||
|
author: Max Gialanella
|
||||||
|
tags:
|
||||||
|
- bash
|
||||||
|
- linux
|
||||||
|
categories: []
|
||||||
|
date: 2023-09-10 18:26:00
|
||||||
|
---
|
||||||
|
|
||||||
|
Running a bash script on system start can be an involved process, depending on you distro. The proper way is to create a system service and plug it into /init.d but you can leverage the crontab if you want a simple quick way to run something on startup.
|
||||||
|
|
||||||
|
How to run a script on start up/reboot
|
||||||
|
Create Script
|
||||||
|
`cd` return to user home
|
||||||
|
`vim startup.sh` create script
|
||||||
|
`chmod +x startup.sh` Make script executable
|
||||||
|
`crontab -e` Edit crontab
|
||||||
|
|
||||||
|
Add the line
|
||||||
|
`@reboot sh $HOME/startup.sh`
|
||||||
|
|
||||||
|
Now your script will run on reboot.
|
||||||
|
[Source Stack overflow thread](https://stackoverflow.com/a/29247942)
|
145
content/blog/Sending-Emails-with-Cloudflare-Workers.md
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
---
|
||||||
|
title: Sending Emails with Cloudflare Workers
|
||||||
|
author: Max Gialanella
|
||||||
|
tags: []
|
||||||
|
categories: []
|
||||||
|
date: 2023-10-01 20:12:00
|
||||||
|
---
|
||||||
|
|
||||||
|
Cloudflare has a partnership with MailChannels which has allowed Cloudflare to introduce email sending into its web workers. There is some documentation to set this up but its all over the place. Here are the steps I took to get email sending running, using workers.
|
||||||
|
|
||||||
|
Before getting started you want to generate public and private keys for your DKIM records.
|
||||||
|
I grabbed steps from this guide -> https://github.com/cloudsecurityalliance/webfinger.io/blob/main/docs.webfinger.io/DKIM-setup.md
|
||||||
|
|
||||||
|
###### Generate a DKIM private and public key:
|
||||||
|
|
||||||
|
Private key as PEM file and base64 encoded txt file:
|
||||||
|
|
||||||
|
```
|
||||||
|
openssl genrsa 2048 | tee priv_key.pem | openssl rsa -outform der | openssl base64 -A > priv_key.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
Public key as DNS record:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo -n "v=DKIM1;p=" > pub_key_record.txt && \
|
||||||
|
openssl rsa -in priv_key.pem -pubout -outform der | openssl base64 -A >> pub_key_record.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
###### Setup DNS records:
|
||||||
|
|
||||||
|
SPF record:
|
||||||
|
`TXT`, `YOUR DOMAIN.COM`, `v=spf1 ~all`
|
||||||
|
|
||||||
|
DMARC record:
|
||||||
|
`TYT`,
|
||||||
|
`_dmark`,
|
||||||
|
`v=DMARC1; p=none;rua=mailto:741da103196f4adba4f119840d7b8919@dmarc-reports.cloudflare.net`
|
||||||
|
|
||||||
|
Mail Channels Record:
|
||||||
|
|
||||||
|
> Important note, this is the domain of your worer sending emails. Its probably something like "dev.yourdomain.com" check your worker setup.
|
||||||
|
> `TXT`,`_mailchannels`,`v=mc1 cfid=YOUR DOMAIN.COM`
|
||||||
|
|
||||||
|
Mailchannels Domain Key Record:
|
||||||
|
`TXT`,`mailchannels._domainkey`,`CONTENTS OF pub_key_record.txt`
|
||||||
|
|
||||||
|
###### Setup a new worker for sending emails
|
||||||
|
|
||||||
|
Go into cloudflare and setup a new worker.js and paste in the following code.
|
||||||
|
|
||||||
|
```
|
||||||
|
addEventListener("fetch", event => {
|
||||||
|
event.respondWith(handleRequest(event.request))
|
||||||
|
})
|
||||||
|
|
||||||
|
async function handleRequest(request) {
|
||||||
|
|
||||||
|
let respContent = "";
|
||||||
|
|
||||||
|
// only send the mail on "POST", to avoid spiders, etc.
|
||||||
|
if( request.method == "POST" ) {
|
||||||
|
|
||||||
|
const formData = await request.formData();
|
||||||
|
const body = {};
|
||||||
|
for (const entry of formData.entries()) {
|
||||||
|
body[entry[0]] = entry[1];
|
||||||
|
}
|
||||||
|
fls = JSON.parse(JSON.stringify(body));
|
||||||
|
|
||||||
|
let send_request = new Request("https://api.mailchannels.net/tx/v1/send", {
|
||||||
|
"method": "POST",
|
||||||
|
"headers": {
|
||||||
|
"content-type": "application/json",
|
||||||
|
},
|
||||||
|
"body": JSON.stringify({
|
||||||
|
"personalizations": [
|
||||||
|
{ "to": [ {"email": "RECIPIENT@EMAIL.COM",
|
||||||
|
"name": 'Email Tester'}],
|
||||||
|
"dkim_domain": 'YOURDOMAIN.com',
|
||||||
|
"dkim_selector": 'mailchannels',
|
||||||
|
"dkim_private_key": `<${PrivateKey}>`,
|
||||||
|
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"from": {
|
||||||
|
"email": "admin@ravenwulfconsulting.com",
|
||||||
|
"name": "admin",
|
||||||
|
},
|
||||||
|
"reply_to": {
|
||||||
|
"email": `${body.email}`,
|
||||||
|
"name": `${body.name || 'No Name Provided'}`,
|
||||||
|
},
|
||||||
|
"subject": `${body.subject || 'No Subject'}`,
|
||||||
|
"content": [{
|
||||||
|
"type": "text/plain",
|
||||||
|
"value":
|
||||||
|
`Email: ${body.email}
|
||||||
|
Name: ${body.name || 'No Name Provided'}
|
||||||
|
|
||||||
|
${body.message || 'No Message'}
|
||||||
|
`,
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const resp = await fetch(send_request);
|
||||||
|
respContent = resp.status + " " + resp.statusText
|
||||||
|
}
|
||||||
|
|
||||||
|
let htmlContent = "<html><head></head><body><pre>" +
|
||||||
|
`
|
||||||
|
<form method="post">
|
||||||
|
Sub: <input type="text" name="subject" value="Testing email sending" /><br>
|
||||||
|
Name: <input type="text" name="name" value="Testman Testerguy" /><br>
|
||||||
|
Email: <input type="text" name="email" value="testformsubmit@gmail.com" /><br>
|
||||||
|
Msg: <input type="text" name="message" value="This is a test email to test the email send worker" /><br>
|
||||||
|
<input type="submit" value="Send"/>
|
||||||
|
</form>
|
||||||
|
` +
|
||||||
|
"<pre>" + respContent + "</pre>" +
|
||||||
|
"</body></html>";
|
||||||
|
return new Response(htmlContent, {
|
||||||
|
headers: { "content-type": "text/html" },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This code is crap and extremely insecure. Its a combination of code from various sources. Its super crappy. Its just a simple foundation to get your own worker set up.
|
||||||
|
|
||||||
|
Pay close attention to the status messages after posting the form.
|
||||||
|
|
||||||
|
- 200 - Success
|
||||||
|
- 400 - DNS records are not set up properly, or didn't propagate. Mailchannels is rejecting request.
|
||||||
|
- 500 - Post data isn't correct. You won't get any error messages, just a 500
|
||||||
|
|
||||||
|
Best of luck getting everything running.
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
|
||||||
|
- Seting up DKIM Records: https://github.com/cloudsecurityalliance/webfinger.io/blob/main/docs.webfinger.io/DKIM-setup.md
|
||||||
|
- Cloudflare DKIM Explnained: https://www.cloudflare.com/en-ca/learning/dns/dns-records/dns-dkim-record/
|
||||||
|
- Mailchannels Adding DKIM to workers: https://support.mailchannels.com/hc/en-us/articles/7122849237389-Adding-a-DKIM-Signature
|
||||||
|
- Email Worker Code: https://gist.github.com/IhsanGan/6111b59b9a7b022b5897d28d8454ad8d
|
||||||
|
- Email Worker Post: https://support.mailchannels.com/hc/en-us/articles/4565898358413-Sending-Email-from-Cloudflare-Workers-using-MailChannels-Send-API
|
||||||
|
- Tons of snippets from this thread: https://community.cloudflare.com/t/send-email-from-workers-using-mailchannels-for-free/361973
|
28
content/blog/Setup-nginx-to-point-subdomain-at-port.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
title: Setup nginx to point subdomain at port
|
||||||
|
author: Max
|
||||||
|
tags:
|
||||||
|
- home server
|
||||||
|
categories:
|
||||||
|
- computers
|
||||||
|
date: 2023-01-01 04:39:00
|
||||||
|
---
|
||||||
|
|
||||||
|
You can setup nginx to point subdomains at specific ports.
|
||||||
|
|
||||||
|
Set up your a records
|
||||||
|
|
||||||
|
set up nginx
|
||||||
|
|
||||||
|
```
|
||||||
|
server {
|
||||||
|
server_name blog.maxg.cc www.blog.maxg.cc;
|
||||||
|
listen 80;
|
||||||
|
root /data/blog/folder;
|
||||||
|
index index.html;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-1.png)
|
||||||
|
|
||||||
|
OK THEN
|
15
content/blog/Sleep-Linux-Mint-Keyboard-Shortcut.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
title: Sleep Linux Mint Keyboard Shortcut
|
||||||
|
tags:
|
||||||
|
- linux
|
||||||
|
categories: []
|
||||||
|
date: 2023-01-14 18:18:45
|
||||||
|
---
|
||||||
|
|
||||||
|
Sleep Linux Mint with this keyboard shortcut
|
||||||
|
|
||||||
|
`CTRL + ALT + END`
|
||||||
|
|
||||||
|
This shortcut was oddly challenging to find.
|
||||||
|
I hope others enjoy using it as much as I do.
|
||||||
|
Goodnight
|
32
content/blog/What-am-I-doing.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
title: Get .env file variables into bash scripts
|
||||||
|
tags:
|
||||||
|
- bash
|
||||||
|
categories: []
|
||||||
|
author: Max
|
||||||
|
date: 2023-01-01 04:07:00
|
||||||
|
---
|
||||||
|
|
||||||
|
If your server has a .env file, it may be necessary to parse those variables into a bash script. This can be accomplished by using the 'source' command.
|
||||||
|
|
||||||
|
A .env file is an important part of any application set up because it allows you to separate credentials of the app into different environments and pulls them out of the git repository.
|
||||||
|
|
||||||
|
Contents of a .env file may look like this:
|
||||||
|
DB_USERNAME=root
|
||||||
|
DB_PASSWORD=S0S3CUR3!
|
||||||
|
|
||||||
|
## How to pull .env variables into a bash script:
|
||||||
|
|
||||||
|
Make sure to start with the right [shebang][1] at the top of your file.
|
||||||
|
|
||||||
|
> #!/bin/bash
|
||||||
|
|
||||||
|
Pull in .env variables
|
||||||
|
|
||||||
|
> source ~/.env
|
||||||
|
|
||||||
|
Then reference those variables in your script
|
||||||
|
|
||||||
|
> echo "$DB_USERNAME"
|
||||||
|
|
||||||
|
[1]: https://earthly.dev/blog/understanding-bash/
|
17
content/blog/Windows-Hello-for-Linux.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: Windows Hello for Linux
|
||||||
|
tags: []
|
||||||
|
categories: []
|
||||||
|
date: 2023-01-01
|
||||||
|
---
|
||||||
|
|
||||||
|
There is a program called Howdy, which is like Windows Hello. It uses face data as authentication.
|
||||||
|
[Howdy Github Repository][1]
|
||||||
|
|
||||||
|
![howdy logo](http://blog.maxg.cc/images/pasted-3.png)
|
||||||
|
|
||||||
|
If you own a Logitech Brio or other camera with Windows Hello compatibility, Howdy will work perfectly.
|
||||||
|
Howdy is better than windows hello though. It has a serious advantage while you are running it in linux; any time you would need to type in your password, howdy will verify with your camera. You won't have to type your password in for any authentication on your linux machine even on command line!
|
||||||
|
|
||||||
|
[1]: https://github.com/boltgolt/howdy
|
||||||
|
[2]: /usr/uploads/2023/01/92500213.png
|
19
content/blog/android-ignore-folder-contents.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
title: Tell Android to ignore folder contents
|
||||||
|
tags:
|
||||||
|
- android
|
||||||
|
date: 2023-01-14
|
||||||
|
---
|
||||||
|
|
||||||
|
Tired of showing the contents of your audio books library in your music app?
|
||||||
|
|
||||||
|
Many Android applications scan local directories and display the contents when you are trying to say, add an image to a text message.
|
||||||
|
|
||||||
|
> a `.nomedia` file tells android to ignore folder contents when doing automatic scans for a file type.
|
||||||
|
|
||||||
|
Using an app like Solid Explorer, browse into the folder you want to exclude, create a new file and call it `.nomedia`. Thats it, you are done.
|
||||||
|
|
||||||
|
For example, if you have an "audio-books" folder, you don't want that appearing in your music app.
|
||||||
|
If you have a "spicy memes" folder, you don't want that appearing in your photos app.
|
||||||
|
|
||||||
|
Android has a built in mechanism that tells the system "Hey, ignore the contents of this folder." Simply browse into the folder (On your phone) and create an empty file, name that file `.nomedia`. Thats it! Android will now ignore that folder.
|
@ -4,11 +4,15 @@ description: "Creating a working ergonomic keyboard. From files to physical."
|
|||||||
date: "2023-10-1"
|
date: "2023-10-1"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
![atreyu complete](/keyboards/completeatreyu.jpg){.banner2}
|
||||||
|
|
||||||
### It started with an existing keyboard
|
### It started with an existing keyboard
|
||||||
|
|
||||||
It all began with the [lily58](https://www.littlekeyboards.com/collections/lily58-pcb-kits/products/lily58-pro-pcb-kit). An ergonomic keyboard that has 58 keys. I loved the design and layout. But it wasn't portable. It required a large amount of desk space to function comfortably.
|
It all began with the [lily58](https://www.littlekeyboards.com/collections/lily58-pcb-kits/products/lily58-pro-pcb-kit). An ergonomic keyboard that has 58 keys. I loved the design and layout. But it wasn't portable. It required a large amount of desk space to function comfortably with palm wrests and wires running everywhere to connect the two halves of the board and the board to the computer.
|
||||||
|
|
||||||
I began to browse around for other options. A portable, wireless, lily58 keyboard.
|
I began to browse around for other options. A portable, wireless, lily58 keyboard. Did such a thing even exist?
|
||||||
|
|
||||||
|
![lilly banner](/keyboards/lillybanner.jpg)
|
||||||
|
|
||||||
### Finding the right project
|
### Finding the right project
|
||||||
|
|
||||||
@ -20,7 +24,7 @@ You need to fabricate and assemble this keyboard from the files on github.
|
|||||||
|
|
||||||
### Exporting the cutter files and fabrication
|
### Exporting the cutter files and fabrication
|
||||||
|
|
||||||
Using KiCad (An open source cad program for linux) I opened, customized and finally, after much reading and tweaking, exported the cutter files. Cutter files are used by PCB manufacturers to produce PCBs. I uploaded the files to Elecrow, a manufacturer in China. Then waited patiently for the PCBs to arrive in the mail.
|
Using [KiCad](https://www.kicad.org/) (An open source cad program for linux) I opened, customized and finally, after much reading and tweaking, exported the cutter files. Cutter files are used by PCB manufacturers to produce PCBs. I uploaded the files to Elecrow, a manufacturer in China. Then waited patiently for the PCBs to arrive in the mail.
|
||||||
|
|
||||||
### Building and programming
|
### Building and programming
|
||||||
|
|
||||||
@ -30,6 +34,24 @@ Understanding the ZMK firmware was a challenge. The way you program the keyboard
|
|||||||
|
|
||||||
[After much trial and error](https://github.com/stimularity/zmk-config/commits/main) the keyboard was ready for action.
|
[After much trial and error](https://github.com/stimularity/zmk-config/commits/main) the keyboard was ready for action.
|
||||||
|
|
||||||
|
![zmk config example](/keyboards/zmkconfig.png)
|
||||||
|
Example of zmk header for Dvorak layout
|
||||||
|
|
||||||
### Blank Keycaps
|
### Blank Keycaps
|
||||||
|
|
||||||
At first the blank keycaps were a cost saving measure. Keycaps without legends are considerably cheaper. But after some time using them, I have come to love them. Despite being able to touch type people generally still look at the keys frequently for numbers and symbols. Without any reference, you learn to touch type them as well. Ultimately it has made me a faster typist.
|
At first the blank keycaps were a cost saving measure. Keycaps without legends are considerably cheaper. But after some time using them, I have come to love them. Despite being able to touch type people generally still look at the keys frequently for numbers and symbols. Without any reference, you learn to touch type them as well. Ultimately it has made me a faster typist.
|
||||||
|
|
||||||
|
# My first build with the Atreyu PCB
|
||||||
|
|
||||||
|
Used a large battery which I drew a mutant frog on the tape.
|
||||||
|
![another atreyu](/keyboards/anotheratreyu.jpg)
|
||||||
|
|
||||||
|
# First build and second build
|
||||||
|
|
||||||
|
![atreyu no caps](/keyboards/atreyunocaps.jpg)
|
||||||
|
![atreyu various switches](/keyboards/atreyuvariuswitches.jpg)
|
||||||
|
|
||||||
|
# Atreyu Compared to lily58
|
||||||
|
|
||||||
|
Same layout, different designs
|
||||||
|
![comparison](/keyboards/lilyandatreyu.jpg)
|
||||||
|
@ -5,25 +5,31 @@ icon: "/solidscribe.png"
|
|||||||
date: "2023-10-1"
|
date: "2023-10-1"
|
||||||
---
|
---
|
||||||
|
|
||||||
Solid Scribe is an end-to-end encrypted note taking application I created for personal convenience and privacy.
|
![Solid Scribe Logo](/covers/solidscribeicon.svg){.banner}
|
||||||
|
|
||||||
### Application overview
|
[www.SolidScribe.com](https://www.solidscribe.com/) is a live application. You can sign up for free and use it right now.
|
||||||
|
|
||||||
Solid Scribe is an encrypted note taking application that respects users privacy.
|
Solid Scribe is a zero-access encrypted note taking application. Created for convenience and privacy.
|
||||||
|
|
||||||
### Why it was created
|
### Why it was created
|
||||||
|
|
||||||
I created solid scribe because I was tired of all my data being scraped and put into a giant marketing profile. Daily notes contain a lot of private information, giving all that data to google or facebook made me uncomfortable.
|
I created solid scribe because I was tired of all my data being scraped and put into a giant marketing profile. Daily notes contain a lot of private information, giving all that data to google or facebook made me uncomfortable. I encouraged my friends to use SolidScribe because all their private data was being read by big corporations.
|
||||||
|
|
||||||
### How it works
|
One of my friends argued "I would rather have google read my notes than someone I know." This lead me to note encryption. Without a password, all notes are unreadable.
|
||||||
|
|
||||||
Solid Scribe is end to end encrypted with note text completely encrypted using a private key. Any time a note is created a new encrypted database entry is created. Note text can not be read without the correct decryption key.
|
### How it works - Security
|
||||||
|
|
||||||
|
When a note is made, a database entry is created with note text and random noise. This noise is encrypted with the note text to increase entropy. No two notes are the same. When a user access this not, their encryption key decrypts the text and they can edit it. All encryption keys are stored on the server, encrypted with the users password. This is to prevent users from losing them or attempting to falsify their data for access to other users information.
|
||||||
|
|
||||||
|
### Zero Access Encryption
|
||||||
|
|
||||||
|
Note data is stored on the server encrypted. If someone leaked the database and took all the information, note data would not be readable. Without the users password for decryption, nothing can be read. All requests send a json web token with a session id and a session key. This session key is used to decrypt your session on the server. Yes, even the session data stored on the server is encrypted. These sessions tokens expire and are renewed every 100 requests. If a session token does not decrypt properly, all sessions for that user are revoked. Even if an attacker gained access to all the data on the server and your computer browser information, they would only have a small window for an attack.
|
||||||
|
|
||||||
### Tech Stack
|
### Tech Stack
|
||||||
|
|
||||||
Solid Scribe is hosted on linode, using nginx and express router.
|
- Solid Scribe is hosted on linode, using NGINX and Express router.
|
||||||
The backend is fully Node.js without an ORM and minimal frameworks.
|
- The backend is a fully custom Node.js server without an ORM and minimal frameworks to support maintainability and minimize attack vectors.
|
||||||
Frontend Vue.js using Vue-CLI, Socket.io and Semanic UI for the styles.
|
- The frontend Vue.js using Vue-CLI, Socket.io and Sematic UI for the styles.
|
||||||
|
|
||||||
### Current Major Features
|
### Current Major Features
|
||||||
|
|
||||||
@ -38,7 +44,7 @@ Frontend Vue.js using Vue-CLI, Socket.io and Semanic UI for the styles.
|
|||||||
- Inserting of link metadata into note
|
- Inserting of link metadata into note
|
||||||
- Secure sharing of notes with other users using public-key encryption
|
- Secure sharing of notes with other users using public-key encryption
|
||||||
- Synchronous note editing across open note instances
|
- Synchronous note editing across open note instances
|
||||||
- Pushing links from web to your account using a bookmarklet
|
- Securley pushing URLs from browser to your account using a bookmarklet
|
||||||
|
|
||||||
### Source Code
|
### Source Code
|
||||||
|
|
||||||
|
98
content/blog/crDroid-OnePlus-7-pro-update.md
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
---
|
||||||
|
title: crDroid 9.1 OnePlus 7 pro install/update
|
||||||
|
author: Max Gialanella
|
||||||
|
tags:
|
||||||
|
- android
|
||||||
|
- crdroid
|
||||||
|
categories: []
|
||||||
|
date: 2023-01-14 17:54:07
|
||||||
|
---
|
||||||
|
|
||||||
|
This will walk you through **installing a custom rom** on your phone, **updating the firmware** and **installing google apps**. Then **rooting your phone**.
|
||||||
|
|
||||||
|
This tutorial is intended for a **OnePlus 7 Pro**, executed on a Debian based Linux machine but the same steps can be applied to windows. I'm running Linux Mint.
|
||||||
|
|
||||||
|
Any custom android rom requires an unlocked bootloader. If your bootloader is not unlocked, find a tutorial on how to do that.
|
||||||
|
If this is your first time installing the crDroid, you should factory reset your phone.
|
||||||
|
|
||||||
|
#### Install Android platform tools
|
||||||
|
|
||||||
|
Here is a good explanation on android debug bridge (ADB) and other tools -> https://wiki.lineageos.org/adb_fastboot_guide
|
||||||
|
Here is a link for platform specific setups.
|
||||||
|
https://www.xda-developers.com/install-adb-windows-macos-linux/#how-to-set-up-adb
|
||||||
|
|
||||||
|
On Linux you can just use a package manager to install the required tools:
|
||||||
|
`sudo apt-get install android-tools-adb android-tools-fastboot`
|
||||||
|
|
||||||
|
#### Download all required packages
|
||||||
|
|
||||||
|
Navigate to -> https://crdroid.net/guacamole/9 and Download:
|
||||||
|
|
||||||
|
- **Latest ROM** click -> "Download latest version" button
|
||||||
|
- **Latest Firmware** click -> "Firmware" button and download latest version
|
||||||
|
- **Latest Gapps** click -> "Gapps" button -> Latest folder -> Download the Gapps version you need. If you are unsure, just grab "NikGapps-stock-..."
|
||||||
|
- **Latest Recovery** -> Recovery -> Download Latest Version. If your recovery is not the crDroid recovery, download it now.
|
||||||
|
|
||||||
|
#### Testing your tools are set up correctly
|
||||||
|
|
||||||
|
Open a terminal window and type in `adb --version` make sure it prints out the version and the installed path. Do the same again with `fastboot --version`.
|
||||||
|
|
||||||
|
Its essential to have both fastboot and adb accessible and set up correctly or the firmware update script won't work correctly.
|
||||||
|
|
||||||
|
#### Connect to your phone via USB and enable USB debugging
|
||||||
|
|
||||||
|
- Grab your Phone. Make sure you enable USB Debugging in the developer menu.
|
||||||
|
- On your machine run `sudo adb devices`
|
||||||
|
- On your phone you should get a prompt, Allow USB Debugging? YES!
|
||||||
|
- Your computer should list the connected devices. Now reboot your phone to the bootloader with the command
|
||||||
|
- `adb reboot bootloader` your phone will restart to the bootloader.
|
||||||
|
|
||||||
|
#### Enter fastboot to install crDroid recovery
|
||||||
|
|
||||||
|
- Plug in your phone and use command `adb reboot fastboot` to boot into fastboot.
|
||||||
|
- Flash the crDroid recovery boot.img with command `fastboot flash boot boot.img`
|
||||||
|
- Now restart to recovery with command `fastboot reboot recovery`
|
||||||
|
- Make sure crDroid recovery installed correctly.
|
||||||
|
|
||||||
|
#### Enter fastboot to apply firmware update
|
||||||
|
|
||||||
|
- Inside the bootloader, use the up/down volume buttons until the top says "Recovery Mode" press the lock button to select. The phone will boot into recovery mode.
|
||||||
|
- Select "Advanced" -> "Enter Fastboot"
|
||||||
|
- Your phone is now ready for the firmware update. On your computer, extract "OP7Pro firmware flash tool.zip" and enter the folder. You will see "Update-firmware.bat" and "Update-firwmare.sh"
|
||||||
|
- On windows you can just double click "update-firmware.bat"
|
||||||
|
- On Linux run the command `./Update-firmware.sh` then follow the prompts on screen. (Yes to everything)
|
||||||
|
- Once the update is complete, on your phone press "Enter Recovery"
|
||||||
|
|
||||||
|
#### Enter recovery to sideload packages
|
||||||
|
|
||||||
|
- Inside the bootloader, use the up/down volume buttons until the top says "Recovery Mode" press the lock button to select. The phone will boot into recovery mode.
|
||||||
|
- Select "Apply Update" -> "Apply from adb"
|
||||||
|
- Your phone is now ready for packages from your computer.
|
||||||
|
On your computer:
|
||||||
|
- **Update Rom**: run the command `adb sideload <crdroid update.zip>`
|
||||||
|
- Reboot to recovery again.
|
||||||
|
- **Update Gapps**: run the command `adb sideload <selected gapps.zip>`
|
||||||
|
- "Reboot system now"
|
||||||
|
|
||||||
|
#### Root your phone
|
||||||
|
|
||||||
|
- Make sure you booted into your phone and unlocked it. Make sure all updates are complete.
|
||||||
|
- Browse to -> https://themagisk.com/ and download the magisk.apk
|
||||||
|
- Install the magisk.apk on your phone.
|
||||||
|
- Reboot back into recovery `adb reboot recovery` and select "Apply Update" -> "Apply from adb"
|
||||||
|
- Browse to -> https://themagisk.com/ on your computer and download the SAME magisk.apk
|
||||||
|
- Rename "Magisk.apk" to "Magisk.zip"
|
||||||
|
- Now sideload the apk straight into your phone `adb sideload Magisk.zip`
|
||||||
|
- "Reboot system now"
|
||||||
|
- On your phone, download and install the magisk.apk
|
||||||
|
- You can now do rooted things.
|
||||||
|
|
||||||
|
#### Unable to mount error
|
||||||
|
|
||||||
|
- If you see this error its because your data partition is encrypted. Do not worry about it. You can still access your phone with ADB.
|
||||||
|
|
||||||
|
#### Useful ADB Commands
|
||||||
|
|
||||||
|
- Print a list of connected devices: `adb devices`
|
||||||
|
- Kill the ADB server: `adb kill-server`
|
||||||
|
- Install a package: `adb install <path to apk or zip file>`
|
@ -18,7 +18,7 @@ The logo of Ravenwulf was challenging to design. The request was to create a uni
|
|||||||
|
|
||||||
Ravenwulf is powered by Nuxt.js with the front end built using TailwindCss. I have never used either of these technologies before but they are modern and well documented.
|
Ravenwulf is powered by Nuxt.js with the front end built using TailwindCss. I have never used either of these technologies before but they are modern and well documented.
|
||||||
|
|
||||||
I chose to use nuxt.js because its of declarative routing, server side rendering, good SEO options and most importantly, it uses Vue.js. Im a big Vue fan. I dont own any Vue clothing but its only a matter of time.
|
I chose to use nuxt.js because its of declarative routing, server side rendering, good SEO options and most importantly, it uses Vue.js. Im a big Vue fan. I don't own any Vue swag but its only a matter of time. The declarative routing, which builds pages and routes based on files in a directory also allows the client to create new content without the need for developer interaction.
|
||||||
|
|
||||||
Next, I chose TailwindCSS because of all the hype. Was it really all its cracked up to be? Why relearn 100's of CSS selectors all over again just to get some new shorthand options? After spending some time with it, the short answer is "Hell Yes! Its good!"
|
Next, I chose TailwindCSS because of all the hype. Was it really all its cracked up to be? Why relearn 100's of CSS selectors all over again just to get some new shorthand options? After spending some time with it, the short answer is "Hell Yes! Its good!"
|
||||||
|
|
||||||
@ -28,16 +28,18 @@ That's all I needed for this project. Almost all the configurations are the defa
|
|||||||
|
|
||||||
I didn't want to spend much money on hosting. I actually didn't want to spend any money. This is where Cloudflare Pages enters the picture. They offer free hosting, for lower traffic projects, on their super robust edge network.
|
I didn't want to spend much money on hosting. I actually didn't want to spend any money. This is where Cloudflare Pages enters the picture. They offer free hosting, for lower traffic projects, on their super robust edge network.
|
||||||
|
|
||||||
Cloudflare offers automatic builds. To trigger them, simply push to a Git Repo. Within minutes I had Ravenwulf in a git repo and connected to Cloudflare Pages. Just like that, the site was live.
|
Cloudflare offers automatic builds. To trigger them, simply push to a Git Repo. Within minutes I had Ravenwulf on github and connected to Cloudflare Pages. Just like that, the site was live.
|
||||||
|
|
||||||
Hooking up the "Contact Form" and Sending email from the ravenwulf was the only part of this project that was truly a headache. Mostly because the feature is new and the documentation is a mess. After much struggling, the contact form was setup and working. [I detailed a setup guide here.](https://blog.maxg.cc/2023/10/01/Sending-Emails-with-Cloudflare-Workers/)
|
Hooking up the "Contact Form" and Sending email from the Ravenwulf was the only part of this project that was truly a headache. Mostly because the feature is new and the documentation is a mess. After much struggling, the contact form was setup and working. [I detailed a setup guide here.](https://blog.maxg.cc/2023/10/01/Sending-Emails-with-Cloudflare-Workers/)
|
||||||
|
|
||||||
### Thoughts on the Ravenwulf Tech Stack
|
### Final thoughts on the Ravenwulf
|
||||||
|
|
||||||
I'm extremely happy with the tech that runs Ravenwulf.com.
|
The design of Ravenwulf is a little boring but that was the clients request. I did my best to take pages of text and make them a little more engaging. I hate websites that try way too hard and mix in a million different styles and images to try and make dry content more engaging. At the end of the day, its better to have a bigger, accessible chunk of text, instead of some fancy but hardly informational page. Not to mention, the work maintaining and building carousels, fly-in effects, parallax effects and all the supporting media, just turns into a chore.
|
||||||
|
|
||||||
|
I'm extremely happy with the tech that runs Ravenwulf. Its modern and maintainable.
|
||||||
|
|
||||||
**TailwindCSS** is a fantastic tool. It made prototyping and building the site a breeze. Its major advantage is how explicit all the CSS declarations become. No more checking the style of .btn then .main then .content then checking the inspector to see how they are being rendered. Its all made clear from a glance at the element. While this does lend itself to more bulky, confusing and cluttered HTML syntax,the benefits completely outweigh the cons. Tailwind provides easy access to flexbox, responsive elements and color pallets. Additionally, almost never checking the inspector in the Browser make tailwind an absolute delight. Despite its added dependencies it will be my go-to on future projects.
|
**TailwindCSS** is a fantastic tool. It made prototyping and building the site a breeze. Its major advantage is how explicit all the CSS declarations become. No more checking the style of .btn then .main then .content then checking the inspector to see how they are being rendered. Its all made clear from a glance at the element. While this does lend itself to more bulky, confusing and cluttered HTML syntax,the benefits completely outweigh the cons. Tailwind provides easy access to flexbox, responsive elements and color pallets. Additionally, almost never checking the inspector in the Browser make tailwind an absolute delight. Despite its added dependencies it will be my go-to on future projects.
|
||||||
|
|
||||||
**Nuxt.js** is a great framework. I barley scratched the surface of what its capable of doing because it does so much out of the box. I set up some pages, a couple components and thats it. It automatically generates routes. It automatically manages component includes. Its dev server is setup with file watching and hot-reloading. One click here, a click there and an entire site is built. There are tons of additional tools and options in Nuxt should anything else arise in the project, im sure nuxt could handle it. It also has a pretty large repository of Plugins.
|
**Nuxt.js** is a great framework. I barley scratched the surface of what its capable of doing because it does so much out of the box. I set up some pages, a couple components and thats it. It automatically generates routes. It automatically manages component includes. Its dev server is setup with file watching and hot-reloading. One click here, a click there and an entire site is built. There are tons of additional tools and options in Nuxt should anything else arise in the project, im sure nuxt could handle it. It also has a pretty large repository of Plugins.
|
||||||
|
|
||||||
**Inkscape** is a great tool but its SVG export options are frustrating to say the least. It supports a large number of tools and options. While browsers only support a small subset of what Inkscape is capable of creating. The internet is riddled with support threads asking why gradients don't render, elements don't appear, layer masks don't work on export or why entire SVGs are empty after saving. If Inkscape had an "export to web" option, it would be a top quality piece of open source software. Without that, its tough to recommend. I guess you can use Adobe Illustrator but I ain't got the money for that.
|
**Inkscape** is a great tool but its SVG export options are frustrating to say the least. It has a large number of tools and options. While browsers only support a small subset of what Inkscape is capable of creating. The internet is riddled with support threads asking why gradients don't render, elements don't appear, layer masks don't work on export or why entire SVGs are empty after saving. If Inkscape had an "export to web" option, it would be a top quality piece of open source software. Without that, its tough to recommend. I guess you can use Adobe Illustrator but I ain't got the money for that.
|
||||||
|
14
content/blog/hello-world.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
title: "Obligatory I am starting a blog, blog post"
|
||||||
|
categories: []
|
||||||
|
tags: []
|
||||||
|
date: 2023-01-01 04:01:31
|
||||||
|
---
|
||||||
|
|
||||||
|
As we fumble around life, doing little projects we end up learning little things and forgetting a lot of things.
|
||||||
|
|
||||||
|
My hope is that someone will google a strange problem and find the strange solution here. I wish to add to the global human corpus of knowledge in a small way.
|
||||||
|
|
||||||
|
I also hope to document things I will forget.
|
||||||
|
|
||||||
|
If you don't find anything you enjoy, why don't you go somewhere else? Its not like I'm monetizing this blog. Your patronage means nothing to me. Hope you have a great day.
|
34
content/blog/pc-builds.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
title: PC Builds
|
||||||
|
author: Max Gialanella
|
||||||
|
tags: []
|
||||||
|
categories: []
|
||||||
|
date: 2023-02-22 19:33:30
|
||||||
|
---
|
||||||
|
|
||||||
|
At some point I became infatuated with the [SAMA IM01 Case](https://www.newegg.com/p/N82E16811197012). At only 22 liters, it can house an ATX power supply and a large cooler. I bought two! Thus began the journey of rebuilding both my PC and my unRaid server into smaller cases.
|
||||||
|
|
||||||
|
#### Server Going into the SAMA
|
||||||
|
|
||||||
|
Had to purchase an ATX motherboard for complete this one.
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-11.png)
|
||||||
|
|
||||||
|
#### Server Complete
|
||||||
|
|
||||||
|
Cramming three hard drives and an SSD into this case, with an ATX power supply wasn't easy. I had to get creative with the mounting. Two are semi mounted on the bottom while the third is mounted into screw holes. There is an additional intake fan mounted below the PSU which was removed for this photo.
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-13.png)
|
||||||
|
|
||||||
|
#### PC going into SAMA
|
||||||
|
|
||||||
|
My PC was already pretty small, with an ATX board, so it wasn't much trouble to transplant it. I couldn't fit my favorite cooler, the NHD15 and had to switch to the Scythe Fuma.
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-12.png)
|
||||||
|
|
||||||
|
#### PC complete
|
||||||
|
|
||||||
|
All in all the build came out nice but I ended up being very frustrated with the noise and performance. I switched all the fans to the [Noctua Noctua NF-P12 redux](https://www.amazon.com/gp/product/B07CG2PGY6?psc=1) which are affordable and perform extremely well.
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-14.png)
|
||||||
|
|
||||||
|
#### Final picture of both of them before cleaning everything up
|
||||||
|
|
||||||
|
![upload successful](http://blog.maxg.cc/images/pasted-15.png)
|
||||||
|
All in all I'm extremely satisfied with how these PCs came out. There isn't much advantage to stuffing everything into a smaller case. Its generally louder and hotter. The only thing you get is satisfaction.
|
24
content/blog/why-ergonomic.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
title: "Why use ergonomic keyboards?"
|
||||||
|
description: "Ergonomic keyboards have a number of benefits."
|
||||||
|
date: "2023-10-1"
|
||||||
|
---
|
||||||
|
|
||||||
|
![argument for ergo](/keyboards/argumentforergo.jpg)
|
||||||
|
|
||||||
|
Ergonomic keyboards are a class of keyboard that do something to conform to the shape of the human body.
|
||||||
|
This class of keyboards exists because keyboards are not ergonomic. This seems like an obvious distinction but imagine if we had non-ergonomic shoes. Shoes that don't fit the shape of a human foot. Would anyone ever use a non-ergonomic shoe over an ergonomic one?
|
||||||
|
|
||||||
|
Imagine walking all day in a non-ergonomic shoe. How uncomfortable. Yet, For some reason we accept that using an uncomfortable keyboard for 8 or more hours a day is fine.
|
||||||
|
|
||||||
|
### Not for human fingers
|
||||||
|
|
||||||
|
Keyboards rows are staggered, while human fingers do up and down.
|
||||||
|
|
||||||
|
### Not for human wrists
|
||||||
|
|
||||||
|
Keyboards are flat which force wrists to pronate, over time this causes wrist issues.
|
||||||
|
|
||||||
|
### Not for human posture
|
||||||
|
|
||||||
|
Keyboards force our hands to be next to one another to type quickly. This closes our posture and forces are arms into weird angles.
|
11
ecosystem.config.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
name: 'Max Resume',
|
||||||
|
port: '3004',
|
||||||
|
exec_mode: 'cluster',
|
||||||
|
instances: 'max',
|
||||||
|
script: './.output/server/index.mjs'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col min-h-screen bg-slate-100">
|
<div class="flex flex-col min-h-screen bg-slate-100 main-body">
|
||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
<footer class="mx-auto w-full text-white bg-zinc-900 p-2"></footer>
|
<footer
|
||||||
|
class="mx-auto w-full text-white bg-zinc-900 p-2 no-print"
|
||||||
|
></footer>
|
||||||
<div
|
<div
|
||||||
class="w-full mx-auto bg-zinc-800 flex flex-col justify-center items-center py-9 text-white fade-in-children"
|
class="w-full mx-auto bg-zinc-800 flex flex-col justify-center items-center py-9 text-white no-print"
|
||||||
>
|
>
|
||||||
<span> Max Gialanella - {{ new Date().getFullYear() }} </span>
|
<span> Max Gialanella - {{ new Date().getFullYear() }} </span>
|
||||||
</div>
|
</div>
|
||||||
|
19
layouts/homepage.vue
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex w-3xl mx-auto">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='hexagons' fill='%239C92AC' fill-opacity='0.25' fill-rule='nonzero'%3E%3Cpath d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"),
|
||||||
|
linear-gradient(135deg, rgba(0, 0, 0, 0) 1%, rgba(0, 8, 70, 0.56) 60%),
|
||||||
|
radial-gradient(
|
||||||
|
circle at left bottom,
|
||||||
|
rgb(179, 0, 193) 0%,
|
||||||
|
rgb(0, 0, 0) 50%
|
||||||
|
);
|
||||||
|
@apply w-full h-full;
|
||||||
|
}
|
||||||
|
</style>
|
@ -4,5 +4,8 @@ export default defineNuxtConfig({
|
|||||||
devtools: { enabled: false },
|
devtools: { enabled: false },
|
||||||
content: {
|
content: {
|
||||||
documentDriven: true
|
documentDriven: true
|
||||||
}
|
},
|
||||||
|
app: {
|
||||||
|
pageTransition: { name: 'page', mode: 'out-in' }
|
||||||
|
},
|
||||||
})
|
})
|
@ -3,7 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nuxt build",
|
"build": "nuxt build && pm2 kill && pm2 start ecosystem.config.js",
|
||||||
"dev": "nuxt dev",
|
"dev": "nuxt dev",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
"preview": "nuxt preview",
|
"preview": "nuxt preview",
|
||||||
|
1046
pages/backup.vue
Normal file
@ -13,7 +13,10 @@
|
|||||||
<div class="pt-4"></div>
|
<div class="pt-4"></div>
|
||||||
<div class="mx-auto max-w-3xl px-4 blog">
|
<div class="mx-auto max-w-3xl px-4 blog">
|
||||||
<h1>{{ page.title }}</h1>
|
<h1>{{ page.title }}</h1>
|
||||||
<h2 class="text-zinc-500 pb-3">Posted on: {{ page.date }}</h2>
|
<p class="text-zinc-500 pb-2">
|
||||||
|
{{ page.description }}
|
||||||
|
<span class="float-right">{{ page.date }}</span>
|
||||||
|
</p>
|
||||||
<!-- <ContentDoc /> -->
|
<!-- <ContentDoc /> -->
|
||||||
<ContentRenderer :key="page._id" :value="page" />
|
<ContentRenderer :key="page._id" :value="page" />
|
||||||
</div>
|
</div>
|
||||||
@ -30,20 +33,26 @@
|
|||||||
<!-- <p>{{ post }}</p> -->
|
<!-- <p>{{ post }}</p> -->
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="hidden">
|
||||||
|
<img src="" alt="" class="banner" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// Find other pages and list them
|
|
||||||
const { data } = await useAsyncData("blog", () => queryContent("/").find());
|
|
||||||
// Find current page content
|
// Find current page content
|
||||||
const { page } = useContent();
|
const { page } = useContent();
|
||||||
// console.log(page.value);
|
|
||||||
// console.log(data.value);
|
// Find other pages and list them
|
||||||
|
const { data } = await useAsyncData("blog", () => queryContent("/").find());
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
document.title = "Projects | Max Gialanella";
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.blog {
|
r .blog {
|
||||||
@apply leading-9 text-base;
|
@apply leading-9 text-base;
|
||||||
}
|
}
|
||||||
.blog a {
|
.blog a {
|
||||||
@ -56,7 +65,7 @@
|
|||||||
@apply pt-5 mb-2 text-xl border-b border-zinc-300;
|
@apply pt-5 mb-2 text-xl border-b border-zinc-300;
|
||||||
}
|
}
|
||||||
.blog img {
|
.blog img {
|
||||||
@apply my-3 shadow-sm;
|
@apply my-3 shadow-md;
|
||||||
}
|
}
|
||||||
.blog p + P {
|
.blog p + P {
|
||||||
@apply pt-4;
|
@apply pt-4;
|
||||||
@ -64,4 +73,15 @@
|
|||||||
.blog ul {
|
.blog ul {
|
||||||
@apply list-disc ml-10;
|
@apply list-disc ml-10;
|
||||||
}
|
}
|
||||||
|
.blog .banner {
|
||||||
|
background-color: #ebebeb;
|
||||||
|
width: 100%;
|
||||||
|
padding: 15px 0;
|
||||||
|
max-height: 150px;
|
||||||
|
}
|
||||||
|
.blog .banner2 {
|
||||||
|
text-align: center;
|
||||||
|
max-height: 150px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="max-links">
|
<div class="flex justify-center items-center w-2xl mx-auto">
|
||||||
<div class="text-box">
|
<div class="flex flex-row flex-wrap items-start w-full">
|
||||||
|
<div class="text-box py-2 w-full">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Type some shit 😘🔎"
|
placeholder="Type some shit 😘🔎"
|
||||||
@ -11,30 +12,18 @@
|
|||||||
v-on:keyup.enter="webSearch"
|
v-on:keyup.enter="webSearch"
|
||||||
ref="search"
|
ref="search"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="suggestions" v-if="suggestions.length > 0">
|
|
||||||
<div
|
|
||||||
class="suggestion"
|
|
||||||
v-for="(suggestion, index) in suggestions"
|
|
||||||
:class="{ active: suggestionIndex == index }"
|
|
||||||
>
|
|
||||||
{{ suggestion }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-for="column in columns" class="column">
|
<div v-for="column in columns" class="w-1/2 md:w-1/4 flex flex-col">
|
||||||
<h2>{{ column }}</h2>
|
<h2 class="capitalize text-center text-white">{{ column }}</h2>
|
||||||
<div
|
<div
|
||||||
v-for="link in sortedLinks(links, column)"
|
v-for="link in sortedLinks(links, column)"
|
||||||
v-if="link?.title"
|
class="p-1 flex flex-col justify-stretch"
|
||||||
class="flex-child"
|
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
:href="setupUrl(link.url)"
|
:href="setupUrl(link.url)"
|
||||||
class="max-link"
|
class="rounded-md bg-slate-200 py-2 md:px-4 glass text-s text-center md:text-left md:text-base"
|
||||||
target="_blank"
|
target="_self"
|
||||||
v-on:click="linkClick"
|
|
||||||
v-if="link.column == column"
|
v-if="link.column == column"
|
||||||
>
|
>
|
||||||
<span class="visual-aid">
|
<span class="visual-aid">
|
||||||
@ -44,7 +33,6 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div class="lip one"></div> -->
|
<!-- <div class="lip one"></div> -->
|
||||||
|
|
||||||
<span
|
<span
|
||||||
@ -53,9 +41,13 @@
|
|||||||
v-html="generateMessage(2)"
|
v-html="generateMessage(2)"
|
||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
layout: "homepage",
|
||||||
|
});
|
||||||
let seed = ref(0);
|
let seed = ref(0);
|
||||||
let clicks = ref(0);
|
let clicks = ref(0);
|
||||||
let inputText = ref("");
|
let inputText = ref("");
|
||||||
@ -115,12 +107,6 @@
|
|||||||
emoji: "🌦️",
|
emoji: "🌦️",
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
column: "web",
|
|
||||||
url: "https://mail.protonmail.com/u/0/inbox",
|
|
||||||
title: "Proton Mail",
|
|
||||||
emoji: "📧",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
column: "web",
|
column: "web",
|
||||||
url: "www.amazon.com",
|
url: "www.amazon.com",
|
||||||
@ -146,7 +132,6 @@
|
|||||||
title: "Butcher Box",
|
title: "Butcher Box",
|
||||||
emoji: "📦",
|
emoji: "📦",
|
||||||
},
|
},
|
||||||
{ column: "web", url: "gmail.com", title: "Gmail", emoji: "✉" },
|
|
||||||
{
|
{
|
||||||
column: "apps",
|
column: "apps",
|
||||||
url: "schwab.com",
|
url: "schwab.com",
|
||||||
@ -173,6 +158,12 @@
|
|||||||
title: "PhotoPrism Import",
|
title: "PhotoPrism Import",
|
||||||
emoji: "📷",
|
emoji: "📷",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
column: "apps",
|
||||||
|
url: "http://192.168.1.6:2342/library/login",
|
||||||
|
title: "PhotoPrism Local",
|
||||||
|
emoji: "📷",
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
column: "apps",
|
column: "apps",
|
||||||
@ -194,12 +185,12 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
// dumb
|
// dumb
|
||||||
{
|
// {
|
||||||
column: "dumb",
|
// column: "dumb",
|
||||||
url: "www.youtube.com",
|
// url: "www.youtube.com",
|
||||||
title: "Youtube",
|
// title: "Youtube",
|
||||||
emoji: "📺",
|
// emoji: "📺",
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
column: "dumb",
|
column: "dumb",
|
||||||
url: "arstechnica.com",
|
url: "arstechnica.com",
|
||||||
@ -231,21 +222,21 @@
|
|||||||
title: "Hack a Day",
|
title: "Hack a Day",
|
||||||
emoji: "☠",
|
emoji: "☠",
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// column: "dumb",
|
||||||
|
// url: "duckduckgo.com",
|
||||||
|
// title: "Duck Duck Go",
|
||||||
|
// emoji: "🦆",
|
||||||
|
// },
|
||||||
|
// { column: "dumb", url: "bing.com", title: "Bing", emoji: "🦑" },
|
||||||
{
|
{
|
||||||
column: "dumb",
|
column: "web",
|
||||||
url: "duckduckgo.com",
|
|
||||||
title: "Duck Duck Go",
|
|
||||||
emoji: "🦆",
|
|
||||||
},
|
|
||||||
{ column: "dumb", url: "bing.com", title: "Bing", emoji: "🦑" },
|
|
||||||
{
|
|
||||||
column: "dumb",
|
|
||||||
url: "google.com",
|
url: "google.com",
|
||||||
title: "Google",
|
title: "Google",
|
||||||
emoji: "🐚",
|
emoji: "🐚",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
column: "dumb",
|
column: "web",
|
||||||
url: "https://www.etsy.com/shop/PowerfulSpell",
|
url: "https://www.etsy.com/shop/PowerfulSpell",
|
||||||
title: "Powerful Spell",
|
title: "Powerful Spell",
|
||||||
emoji: "🧚🏻",
|
emoji: "🧚🏻",
|
||||||
@ -257,10 +248,29 @@
|
|||||||
emoji: "⌨️",
|
emoji: "⌨️",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
column: "web",
|
column: "dumb",
|
||||||
url: "https://store.epicgames.com/en-US/free-games",
|
url: "https://news.ycombinator.com/",
|
||||||
title: "Free Game!",
|
title: "Hacker News",
|
||||||
emoji: "🎮",
|
emoji: "💀",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
column: "dumb",
|
||||||
|
url: "https://tildes.net/",
|
||||||
|
title: "Tildes",
|
||||||
|
emoji: "~",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
column: "apps",
|
||||||
|
url: "https://maxg.cc",
|
||||||
|
title: "Maxg.cc - resume",
|
||||||
|
emoji: "M",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
column: "local",
|
||||||
|
url: "http://192.168.1.164:3002/",
|
||||||
|
title: "Maxg.cc - Dev",
|
||||||
|
emoji: "M",
|
||||||
},
|
},
|
||||||
|
|
||||||
{ url: "", title: "" },
|
{ url: "", title: "" },
|
||||||
@ -284,34 +294,36 @@
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// setup autocomplete
|
// setup autocomplete
|
||||||
Object.keys(this.links).forEach((key) => {
|
Object.keys(links).forEach((key) => {
|
||||||
const link = this.links[key].url;
|
const link = links[key].url;
|
||||||
if (link) {
|
if (link) {
|
||||||
this.autocomplete.push(link);
|
autocomplete.push(link);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// remove duplicates
|
// remove duplicates
|
||||||
// this.autocomplete = [...new Set(this.autocomplete)]
|
// autocomplete = [...new Set(autocomplete)]
|
||||||
|
|
||||||
this.$nextTick(() => {
|
// $nextTick(() => {
|
||||||
this.$refs.search.focus();
|
// $refs.search.focus();
|
||||||
});
|
// });
|
||||||
|
|
||||||
|
document.title = "Home Page";
|
||||||
});
|
});
|
||||||
|
|
||||||
function sortedLinks(inLinks, category) {
|
function sortedLinks(inLinks, category) {
|
||||||
let sortList = [];
|
let sortList = [];
|
||||||
inLinks.forEach((link) => {
|
inLinks.forEach((link) => {
|
||||||
const lowText = this.inputText.toLowerCase();
|
const lowText = String(inputText.value).toLowerCase();
|
||||||
const searchTitle = link.title.toLowerCase().includes(lowText);
|
const searchTitle = link.title.toLowerCase().includes(lowText);
|
||||||
const searchUrl = link.url.toLowerCase().includes(lowText);
|
const searchUrl = link.url.toLowerCase().includes(lowText);
|
||||||
const searchFilter =
|
const searchFilter = inputText == "" || searchTitle || searchUrl;
|
||||||
this.inputText == "" || searchTitle || searchUrl;
|
|
||||||
|
|
||||||
if (link.column == category && searchFilter) {
|
if (link.column == category && searchFilter) {
|
||||||
sortList.push(link);
|
sortList.push(link);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(sortList);
|
||||||
return sortList.sort((a, b) => {
|
return sortList.sort((a, b) => {
|
||||||
return a.title.localeCompare(b.title);
|
return a.title.localeCompare(b.title);
|
||||||
});
|
});
|
||||||
@ -334,9 +346,9 @@
|
|||||||
}
|
}
|
||||||
if (e.code == "Tab") {
|
if (e.code == "Tab") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.suggestionIndex++;
|
suggestionIndex++;
|
||||||
if (this.suggestionIndex > this.suggestions.length - 1) {
|
if (suggestionIndex > suggestions.length - 1) {
|
||||||
this.suggestionIndex = 0;
|
suggestionIndex = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -344,23 +356,23 @@
|
|||||||
function filterLinks(e) {
|
function filterLinks(e) {
|
||||||
// if(e.code == 'Escape'){
|
// if(e.code == 'Escape'){
|
||||||
// e.preventDefault()
|
// e.preventDefault()
|
||||||
// this.suggestions = []
|
// suggestions = []
|
||||||
// this.inputText = ''
|
// inputText = ''
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
// if(e.code == 'ArrowUp'){
|
// if(e.code == 'ArrowUp'){
|
||||||
// e.preventDefault()
|
// e.preventDefault()
|
||||||
// this.suggestionIndex--
|
// suggestionIndex--
|
||||||
// if(this.suggestionIndex <= -1){
|
// if(suggestionIndex <= -1){
|
||||||
// this.suggestionIndex = this.suggestions.length -1
|
// suggestionIndex = suggestions.length -1
|
||||||
// }
|
// }
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
// if(e.code == 'ArrowDown'){
|
// if(e.code == 'ArrowDown'){
|
||||||
// e.preventDefault()
|
// e.preventDefault()
|
||||||
// this.suggestionIndex++
|
// suggestionIndex++
|
||||||
// if(this.suggestionIndex > this.suggestions.length-1){
|
// if(suggestionIndex > suggestions.length-1){
|
||||||
// this.suggestionIndex = 0
|
// suggestionIndex = 0
|
||||||
// }
|
// }
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
@ -369,8 +381,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.suggestionIndex = -1;
|
suggestionIndex = -1;
|
||||||
this.suggestions = [];
|
suggestions = [];
|
||||||
|
|
||||||
const searchString = String(e.target.value)
|
const searchString = String(e.target.value)
|
||||||
.trim()
|
.trim()
|
||||||
@ -381,19 +393,19 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.autocomplete.forEach((entry) => {
|
autocomplete.forEach((entry) => {
|
||||||
const test = entry.toLowerCase().indexOf(searchString);
|
const test = entry.toLowerCase().indexOf(searchString);
|
||||||
if (test >= 0) {
|
if (test >= 0) {
|
||||||
this.suggestions.push(entry);
|
suggestions.push(entry);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.suggestions = this.suggestions.splice(0, 2);
|
suggestions = suggestions.splice(0, 2);
|
||||||
}
|
}
|
||||||
function webSearch(e) {
|
function webSearch(e) {
|
||||||
// go to suggestion
|
// go to suggestion
|
||||||
if (this.suggestions.length >= 1) {
|
if (suggestions.length >= 1) {
|
||||||
window.location.href = `https://${this.suggestions[0]}`;
|
window.location.href = `https://${suggestions[0]}`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,12 +459,10 @@
|
|||||||
var day = days[now.getDay()];
|
var day = days[now.getDay()];
|
||||||
var month = months[now.getMonth()];
|
var month = months[now.getMonth()];
|
||||||
|
|
||||||
this.seed =
|
seed =
|
||||||
parseInt(`${now.getMonth()}${now.getHours()}${now.getDay()}`) +
|
parseInt(`${now.getMonth()}${now.getHours()}${now.getDay()}`) + clicks;
|
||||||
this.clicks;
|
|
||||||
|
|
||||||
let weekday =
|
let weekday = day + ", " + month + " " + now.getDate() + "<sup>th</sup>";
|
||||||
day + ", " + month + " " + now.getDate() + "<sup>th</sup>";
|
|
||||||
|
|
||||||
if (index == 1) {
|
if (index == 1) {
|
||||||
m = [
|
m = [
|
||||||
@ -477,7 +487,7 @@
|
|||||||
[weekday],
|
[weekday],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (index == 2 && this.seed % 2 == 0) {
|
if (index == 2 && seed % 2 == 0) {
|
||||||
m = [
|
m = [
|
||||||
["You", "The world", "The universe", "Your life"],
|
["You", "The world", "The universe", "Your life"],
|
||||||
[
|
[
|
||||||
@ -542,7 +552,7 @@
|
|||||||
["."],
|
["."],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
if (index == 2 && this.seed % 2 == 1) {
|
if (index == 2 && seed % 2 == 1) {
|
||||||
m = [
|
m = [
|
||||||
["Things", "Stuff", "Its", "Everything"],
|
["Things", "Stuff", "Its", "Everything"],
|
||||||
["are not", "ain't", "is not"],
|
["are not", "ain't", "is not"],
|
||||||
@ -572,7 +582,7 @@
|
|||||||
|
|
||||||
m.forEach((part) => {
|
m.forEach((part) => {
|
||||||
// const p = part[Math.floor(Math.random() * part.length)]
|
// const p = part[Math.floor(Math.random() * part.length)]
|
||||||
const p = part[this.seed % part.length];
|
const p = part[seed % part.length];
|
||||||
let space = " ";
|
let space = " ";
|
||||||
if (p == "." || p == "?") {
|
if (p == "." || p == "?") {
|
||||||
space = "";
|
space = "";
|
||||||
@ -582,41 +592,23 @@
|
|||||||
|
|
||||||
return "<span>" + message + "</span>";
|
return "<span>" + message + "</span>";
|
||||||
}
|
}
|
||||||
function linkClick() {
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log("Close a boy");
|
|
||||||
window.open("", "_self").close();
|
|
||||||
}, 250);
|
|
||||||
}
|
|
||||||
function onCluck() {
|
|
||||||
console.log("hi");
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
html {
|
a.glass {
|
||||||
font-family: Roboto, Helvetica Neue, Arial, Helvetica, sans-serif;
|
transition: all 0.4s ease-out;
|
||||||
}
|
}
|
||||||
body {
|
a.glass:hover {
|
||||||
background-image: none;
|
transition: all 0.4s ease-out;
|
||||||
|
/* background-color: #35004d;*/
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='hexagons' fill='%239C92AC' fill-opacity='0.25' fill-rule='nonzero'%3E%3Cpath d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"),
|
backdrop-filter: blur(7px);
|
||||||
linear-gradient(
|
}
|
||||||
135deg,
|
.glass {
|
||||||
rgba(0, 0, 0, 0) 1%,
|
background-color: rgba(255, 255, 255, 0.25);
|
||||||
rgba(0, 8, 70, 0.56) 60%
|
backdrop-filter: blur(3px);
|
||||||
),
|
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||||
radial-gradient(
|
color: white;
|
||||||
circle at left bottom,
|
|
||||||
rgb(179, 0, 193) 0%,
|
|
||||||
rgb(0, 0, 0) 50%
|
|
||||||
);
|
|
||||||
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
height: 100vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: calc(100% - 20px);
|
width: calc(100% - 20px);
|
||||||
margin: 0 10px 15px;
|
margin: 0 10px 15px;
|
||||||
@ -627,154 +619,4 @@
|
|||||||
border: none;
|
border: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
|
||||||
display: inline-block;
|
|
||||||
width: 100%;
|
|
||||||
color: white;
|
|
||||||
font-size: 1.5em;
|
|
||||||
text-align: center;
|
|
||||||
border-bottom: 1px solid white;
|
|
||||||
padding: 0 0 5px 0;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
.large.message {
|
|
||||||
padding: 0 0 5px 0;
|
|
||||||
font-size: 2em;
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
.small.message {
|
|
||||||
padding: 5px 0 15px 0;
|
|
||||||
font-size: 1em;
|
|
||||||
border-bottom: none;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.center-container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 80vh;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.column {
|
|
||||||
width: 25%;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
.max-links {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
align-items: flex-start;
|
|
||||||
align-content: space-evenly;
|
|
||||||
width: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.flex-child {
|
|
||||||
width: calc(100% - 10px);
|
|
||||||
margin: 0 0 10px;
|
|
||||||
}
|
|
||||||
.glass {
|
|
||||||
background-color: rgba(255, 255, 255, 0.25);
|
|
||||||
border-radius: 4px;
|
|
||||||
backdrop-filter: blur(3px);
|
|
||||||
border: 2px solid rgba(255, 255, 255, 0.1);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.max-link {
|
|
||||||
display: inline-block;
|
|
||||||
box-sizing: border-box;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: rgba(255, 255, 255, 0.25);
|
|
||||||
border-radius: 4px;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 0.8em;
|
|
||||||
padding: 10px 10px;
|
|
||||||
text-decoration: none;
|
|
||||||
color: white;
|
|
||||||
word-break: break-word;
|
|
||||||
backdrop-filter: blur(2px);
|
|
||||||
/* border: 2px solid rgba(255,255,255,0.1);*/
|
|
||||||
font-size: 1.1em;
|
|
||||||
}
|
|
||||||
.max-link:hover {
|
|
||||||
transition: all 0.4s ease-out;
|
|
||||||
/* background-color: #35004d;*/
|
|
||||||
backdrop-filter: blur(7px);
|
|
||||||
}
|
|
||||||
.visual-aid {
|
|
||||||
display: inline-block;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 0 5px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-box {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.suggestions {
|
|
||||||
display: inline-block;
|
|
||||||
background-color: white;
|
|
||||||
position: absolute;
|
|
||||||
top: 49px;
|
|
||||||
left: 0px;
|
|
||||||
right: 0;
|
|
||||||
z-index: 2;
|
|
||||||
border-bottom-left-radius: 4px;
|
|
||||||
border-bottom-right-radius: 4px;
|
|
||||||
margin: 0 10px 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
box-shadow: 0px 4px 3px 0px gray;
|
|
||||||
|
|
||||||
background-color: rgba(255, 255, 255, 0.25);
|
|
||||||
backdrop-filter: blur(4px);
|
|
||||||
}
|
|
||||||
.suggestion {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 10px;
|
|
||||||
border-radius: 4px;
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.suggestion.active {
|
|
||||||
background-color: purple;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nose,
|
|
||||||
.lip,
|
|
||||||
.eye {
|
|
||||||
display: inline-block;
|
|
||||||
background-color: rgba(255, 255, 255, 0.18);
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
backdrop-filter: blur(3px);
|
|
||||||
border: 2px solid rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
.lip {
|
|
||||||
width: calc(100% - 35px);
|
|
||||||
}
|
|
||||||
.lip.one {
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 600px) {
|
|
||||||
.max-links {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media only screen and (min-width: 992px) {
|
|
||||||
.max-links {
|
|
||||||
width: 70%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
718
pages/index.vue
@ -1,35 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- resume box -->
|
<!-- resume box -->
|
||||||
|
<!-- dark:bg-slate-900 dark:text-white -->
|
||||||
<div
|
<div
|
||||||
class="container mx-auto flex flex-row flex-wrap max-w-none md:max-w-5xl bg-white paper my-5"
|
class="container mx-auto flex flex-row flex-wrap max-w-none md:max-w-5xl my-5 bg-white paper"
|
||||||
>
|
>
|
||||||
<div
|
<div class="w-full md:w-8/12 flex flex-col fade-in px-6 pt-2">
|
||||||
class="w-full md:w-7/12 flex flex-col items-center justify-center fade-in"
|
<div class="w-full border-b">
|
||||||
>
|
<p class="text-5xl">Max Gialanella</p>
|
||||||
<div class="p-6 pb-1 md:text-center text-sm md:text-base">
|
</div>
|
||||||
<p class="text-5xl md:text-6xl">Max Gialanella</p>
|
<div class="w-full flex flex-row flex-wrap pt-3">
|
||||||
<p class="py-3">
|
<div class="w-full md:w-8/12 text-sm">
|
||||||
Full stack engineer with a decade of professional
|
<p class="subtle">
|
||||||
experience.
|
<span v-if="frontEndView">
|
||||||
<br />Passionate about web technologies & creative
|
<b>Front End Engineer</b> experienced in UI/UX
|
||||||
problem solving.
|
</span>
|
||||||
|
<span v-if="generalView">
|
||||||
|
<b>Full Stack Engineer</b> with over a decade
|
||||||
|
building professional web software.
|
||||||
|
</span>
|
||||||
|
<span v-if="verboseView">
|
||||||
|
Effective and Driven,
|
||||||
|
<b>Full Stack Engineer</b> with over a decade
|
||||||
|
building professional web software.
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="w-full md:w-5/12 flex flex-row justify-around items-center pt-6 fade-in"
|
class="w-6/12 md:w-4/12 flex flex-col justify-center pl-4 text-sm"
|
||||||
>
|
|
||||||
<div class="pl-1 pr-3 bg-zinc-50 rounded-md shadow-sm">
|
|
||||||
<img
|
|
||||||
src="/maxhead.png"
|
|
||||||
alt="Max head photo"
|
|
||||||
class="object-cover h-auto w-[150px]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="flex flex-col justify-start gap-2 text-sm md:text-base"
|
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<EnvelopeIcon class="h-4 w-4 inline subtle" />
|
<EnvelopeIcon class="h-4 w-4 inline subtle" />
|
||||||
@ -51,153 +49,308 @@
|
|||||||
>
|
>
|
||||||
Flagstaff, AZ
|
Flagstaff, AZ
|
||||||
</a>
|
</a>
|
||||||
|
<span class="subtle">(UTC-7)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="w-6/12 sm:visible md:hidden bg-zinc-50 rounded-md shadow-sm"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-on:click="toggleResumeView()"
|
||||||
|
src="/maxhead.png"
|
||||||
|
alt="Max head photo"
|
||||||
|
class="object-cover h-auto w-[150px]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full md:w-7/12 fade-in d1">
|
<div
|
||||||
<!-- astound -->
|
class="hidden md:flex w-4/12 pt-2 flex-row justify-start items-center fade-in"
|
||||||
<div class="p-6 pb-1">
|
>
|
||||||
|
<div class="pl-1 pr-2 ml-5 bg-zinc-50 rounded-md shadow-sm">
|
||||||
|
<img
|
||||||
|
v-on:click="toggleResumeView()"
|
||||||
|
src="/maxhead.png"
|
||||||
|
alt="Max head photo"
|
||||||
|
class="object-cover h-auto w-[150px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full md:w-7/12 fade-in d1 py-2">
|
||||||
|
<h1 class="p-1 pl-6 subtle md:hidden">Work Experience</h1>
|
||||||
|
|
||||||
|
<!-- ravenwulf -->
|
||||||
|
<div class="p-6 py-2">
|
||||||
<div class="w-full flex justify-between border-b accent">
|
<div class="w-full flex justify-between border-b accent">
|
||||||
<div>Astound Commerce</div>
|
<div>Ravenwulf Consulting</div>
|
||||||
|
<div class="text-s text-zinc-600">2023 - 2024</div>
|
||||||
|
</div>
|
||||||
|
<p class="font-bold text-sm py-2">
|
||||||
|
Full Stack Web Developer
|
||||||
|
</p>
|
||||||
|
<p v-if="frontEndView || generalView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Designed logo, corporate identity, built & launched
|
||||||
|
<a
|
||||||
|
href="http://ravenwulfconsulting.com"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>www.ravenwulfconsulting.com</a
|
||||||
|
>, using Tailwind & Nuxt
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Independently engineered
|
||||||
|
<a
|
||||||
|
href="http://ravenwulfconsulting.com"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>Ravenwulf Consulting.</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Designed Ravenwulf logo and corporate identity.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- astound -->
|
||||||
|
<div class="p-6 py-2">
|
||||||
|
<div
|
||||||
|
class="w-full flex justify-between items-center border-b"
|
||||||
|
>
|
||||||
|
<div class="accent">Astound Commerce</div>
|
||||||
<div class="text-s text-zinc-600">2021-2023</div>
|
<div class="text-s text-zinc-600">2021-2023</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="font-bold py-2">
|
|
||||||
|
<p class="font-bold text-sm py-2">
|
||||||
Software Engineer - Salesforce Commerce Cloud
|
Software Engineer - Salesforce Commerce Cloud
|
||||||
</p>
|
</p>
|
||||||
<p>
|
|
||||||
|
<p v-if="frontEndView || generalView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />Joined
|
||||||
|
a team of four, that redesigned storefront UI for
|
||||||
|
fashion brand Rag & Bone
|
||||||
|
</p>
|
||||||
|
<p v-if="frontEndView || generalView">
|
||||||
|
<ChevronRightIcon
|
||||||
|
class="w-3 h-3 accent inline"
|
||||||
|
/>Streamlined, Apple pay, domestic and international
|
||||||
|
payments for Rag & Bone, before a major sale, which
|
||||||
|
facilitated millions in new revenue
|
||||||
|
</p>
|
||||||
|
<!-- verbose -->
|
||||||
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Launched a new SFCC, online storefront for
|
Achieved Salesforce Javascript & B2C Commerce Developer
|
||||||
|
Certifications.
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Joined a team, of four, that launched a redesigned,
|
||||||
|
electronic storefront for major fashion brand,
|
||||||
<a href="https://www.rag-bone.com" target="_blank"
|
<a href="https://www.rag-bone.com" target="_blank"
|
||||||
>Rag & Bone</a
|
>Rag & Bone</a
|
||||||
>
|
>.
|
||||||
using Typescript, Node.JS and other JS technologies.
|
</p>
|
||||||
Updated & streamlined, domestic and international
|
<p v-if="verboseView">
|
||||||
payments before a big sale which facilitated millions in
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
new revenue.
|
Debugged & streamlined, domestic and international
|
||||||
|
payments for Rag & Bone, before a major sale, which
|
||||||
|
facilitated millions in new revenue.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- rws -->
|
<!-- rws -->
|
||||||
<div class="p-6 pb-1">
|
<div class="p-6 py-2">
|
||||||
<div class="w-full flex justify-between border-b accent">
|
<div class="w-full flex justify-between border-b accent">
|
||||||
<div>RWS - IP Services</div>
|
<div>RWS - IP Services</div>
|
||||||
<div class="text-s text-zinc-600">2018 - 2021</div>
|
<div class="text-s text-zinc-600">2018 - 2021</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="font-bold pt-2">Senior Software Engineer</p>
|
<p class="font-bold text-sm py-2">
|
||||||
<p class="py-2">
|
Senior Software Engineer
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />Worked
|
|
||||||
with partners to build a suite of internal tools.
|
|
||||||
Including custom systems for time tracking, invoicing, a
|
|
||||||
live cardwall, dashboards, forms with intelligent
|
|
||||||
validation, extensive reporting and tools allowing for
|
|
||||||
mass data import and export.
|
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="frontEndView || generalView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Worked with managers to create a sophisticated, dynamic
|
Build a large suite of in house business tools with
|
||||||
form-building system that enabled clients to input
|
custom front ends, databases and servers
|
||||||
custom data with intelligent auto-complete rules per
|
|
||||||
client, removing the need for Marketing and
|
|
||||||
Administrative interaction.
|
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="frontEndView || generalView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Fully rebuilt nine legacy, Single Page Applications.
|
Lead a team of five developers. Set team goals for
|
||||||
Worked directly with managers and QA to scope out all
|
improved standards in communication & quality
|
||||||
existing functionality, then wrote scalable
|
</p>
|
||||||
replacements.
|
<p v-if="frontEndView || generalView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Single handedly replaced nine legacy applications.
|
||||||
|
Rewrote frontend and backend code
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
class="font-bold text-sm pt-2"
|
||||||
|
v-if="generalView || frontEndView"
|
||||||
|
>
|
||||||
|
Lead Software Engineer
|
||||||
|
</p>
|
||||||
|
<p v-if="frontEndView || generalView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Conducted interviews, hired and mentored five new
|
||||||
|
developers
|
||||||
|
</p>
|
||||||
|
<p v-if="frontEndView || generalView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Built a release management platform leveraging Azure
|
||||||
|
Pipelines and Bash
|
||||||
|
</p>
|
||||||
|
<p v-if="frontEndView || generalView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Created node.js microservices for file management,
|
||||||
|
processing long jobs and authentication. Effectively
|
||||||
|
offloading system resources and increasing application
|
||||||
|
speed
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="font-bold pt-2">Lead Software Engineer</p>
|
<!-- verbose -->
|
||||||
<p class="py-2">
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Lead a team of developers in system design and releases.
|
Collaborated with partners and managers to build a suite
|
||||||
Pushed for improved standards in communication &
|
of custom business tools. Facilitating major
|
||||||
quality.
|
improvements in efficiency and reliability to clients.
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Leveraged Azure Pipelines and Bash to stand up a DevOps
|
Led project to create a sophisticated form building
|
||||||
suite that automated builds, package management, version
|
system. Which removed the need for Marketing and
|
||||||
control, source compression and dev, stage & prod
|
Administrative interaction with clients.
|
||||||
releases.
|
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Created a highly performant, browser-based PDF
|
Single handedly replaced nine legacy applications by
|
||||||
annotation & highlighting system with Vue. Annotations
|
writing scalable, modern replacements in Vue.
|
||||||
were converted to images and OCR'd for searching,
|
|
||||||
allowing for cataloging of highlighted data across
|
|
||||||
thousands of documents.
|
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Created an email invite tool to orchestrate sending
|
Lead a team of five developers in system design and
|
||||||
thousands of emails, inviting specific users based on
|
architecture. Set team goals for improved standards in
|
||||||
various attributes, reporting stats, tracking user
|
communication & quality.
|
||||||
engagement and managing email queues. Which resulted in
|
</p>
|
||||||
increased product engagement.
|
|
||||||
|
<div class="pagebreak"></div>
|
||||||
|
|
||||||
|
<p class="font-bold text-sm pt-2" v-if="verboseView">
|
||||||
|
Lead Software Engineer
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Collaborated with managers to conduct interviews. Then
|
||||||
|
hired and mentored new developers.
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Leveraged Azure Pipelines to fully automate releases.
|
||||||
|
Minimizing down time and ensuring consistent updates.
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Created a browser-based PDF annotation application.
|
||||||
|
Allowed for cataloguing and searching of highlights
|
||||||
|
across thousands of documents.
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Created an email invite tool to automate the sending of
|
||||||
|
thousands of custom emails. Which resulted in increased
|
||||||
|
product engagement.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- article one -->
|
<!-- article one -->
|
||||||
<div class="p-6 pb-1">
|
<div class="p-6 py-2">
|
||||||
<div class="w-full flex justify-between border-b accent">
|
<div class="w-full flex justify-between border-b accent">
|
||||||
<div>Article One Partners</div>
|
<div>Article One Partners</div>
|
||||||
<div class="text-s text-zinc-600">2013 - 2018</div>
|
<div class="text-s text-zinc-600">2013 - 2018</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="font-bold pt-2">Software Engineer</p>
|
<p class="font-bold text-sm pt-2">Software Engineer</p>
|
||||||
<p class="py-2">
|
<p v-if="generalView || frontEndView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Rewrote outdated jQuery UI font end in Vue.
|
Rewrote outdated jQueryUI front end in React, migrated
|
||||||
|
entire software stack from PHP 5 to 7
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="generalView || frontEndView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Worked to migrate system from PHP 5 to 7.
|
Updated and maintained custom, enterprise, software
|
||||||
|
platform using PHP, Zend, Node.js and Solr
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p
|
||||||
|
class="font-bold text-sm pt-2"
|
||||||
|
v-if="generalView || frontEndView"
|
||||||
|
>
|
||||||
|
Jr Software Engineer
|
||||||
|
</p>
|
||||||
|
<p v-if="generalView || frontEndView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Migrated legacy file system to Azure cloud. Integrated
|
Updated front-end with new CSS styles and libraries for
|
||||||
new packages from PHP to Node.
|
modern and responsive web
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="generalView || frontEndView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Learned to be Agile. Learned to apply Git, Bash and
|
||||||
|
modern web standards to my workflow
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Rewrote outdated jQuery UI font end in React.
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Modernized entire software stack from PHP 5 to 7.
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Migrated legacy file system from local files to Azure
|
||||||
|
cloud.
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Updated systems to be GDPR compliant with intelligent
|
Updated systems to be GDPR compliant with intelligent
|
||||||
data purging and greater respect for user privacy and
|
data purging.
|
||||||
control.
|
|
||||||
</p>
|
</p>
|
||||||
<p class="font-bold pt-2">JR Software Engineer</p>
|
<p class="font-bold text-sm pt-2" v-if="verboseView">
|
||||||
<p class="py-2">
|
JR Software Engineer
|
||||||
|
</p>
|
||||||
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Update old system to use dynamic template engine and
|
Removed Stored procedures from database and integrated
|
||||||
Doctrine ORM.
|
ORM. Improving application speed and reducing overhead.
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Integrated system with external APIs.
|
Integrated system with external APIs.
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Updated front-end with new CSS styles and libraries for
|
Updated front-end with new CSS styles and libraries for
|
||||||
modern and responsive web.
|
modern and responsive web.
|
||||||
</p>
|
</p>
|
||||||
<p class="py-2">
|
<p v-if="verboseView">
|
||||||
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
Learned to apply GIT, Agile, bash, and modern web
|
Learned to be Agile. Learned to apply Git, Bash and
|
||||||
standards.
|
modern web standards to my workflow.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- skills column -->
|
<!-- skills column -->
|
||||||
<div class="w-full md:w-5/12 skills p-6 fade-in d2">
|
|
||||||
<p class="w-full border-b accent">Primary Skills</p>
|
<div class="w-full md:w-5/12 skills p-6 pt-4 fade-in d2">
|
||||||
|
<p class="w-full border-b accent">Key Skills</p>
|
||||||
<p>
|
<p>
|
||||||
Javascript ES6, Node.js, NPM
|
Javascript ES6, Node.js, NPM
|
||||||
<span class="years">10</span>
|
<span class="years">10</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Vue, UI, UX
|
Vue, Nuxt, Tailwind, UI/UX
|
||||||
<span class="years">14</span>
|
<span class="years">14</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -208,17 +361,29 @@
|
|||||||
Linux, Bash
|
Linux, Bash
|
||||||
<span class="years">10</span>
|
<span class="years">10</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
MySQL, PostgreSQL
|
||||||
|
<span class="years">10</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
PHP, Zend 2, Composer
|
||||||
|
<span class="years">6</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="w-full border-b accent mt-2">DevOps Skills</p>
|
||||||
|
<p>
|
||||||
|
Agile, SCRUM
|
||||||
|
<span class="years">8</span>
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
GIT, SVN
|
GIT, SVN
|
||||||
<span class="years">8</span>
|
<span class="years">8</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
MySQL
|
Azure, CI/CD
|
||||||
<span class="years">10</span>
|
<span class="years">4</span>
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Agile, SCRUM
|
|
||||||
<span class="years">8</span>
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
OO Design, Architecture, MVC
|
OO Design, Architecture, MVC
|
||||||
@ -228,17 +393,9 @@
|
|||||||
RESTful, SOAP APIs, SaaS
|
RESTful, SOAP APIs, SaaS
|
||||||
<span class="years">8</span>
|
<span class="years">8</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>Apache, NGINX, DNS</p>
|
||||||
Azure DevOps, CI/CD
|
|
||||||
<span class="years">4</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p class="w-full border-b accent mt-2">Secondary Skills</p>
|
||||||
PHP, Zend 2, Composer
|
|
||||||
<span class="years">6</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="w-full border-b accent">Secondary Skills</p>
|
|
||||||
<p>
|
<p>
|
||||||
Python, Java
|
Python, Java
|
||||||
<span class="years">8</span>
|
<span class="years">8</span>
|
||||||
@ -249,41 +406,256 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>Salesforce Commerce Cloud</p>
|
<p>Salesforce Commerce Cloud</p>
|
||||||
|
|
||||||
<p class="w-full border-b accent">Certifications</p>
|
<p class="w-full border-b accent mt-2">Certifications</p>
|
||||||
<p>Salesforce Javascript Developer</p>
|
<p>Salesforce Javascript Developer</p>
|
||||||
<p>Salesforce B2C Commerce Developer</p>
|
<p>Salesforce B2C Commerce Developer</p>
|
||||||
<!-- <a href="https://trailblazer.me/id/mgialanella" target="_blank">View Certifications</a> -->
|
<!-- <a href="https://trailblazer.me/id/mgialanella" target="_blank">View Certifications</a> -->
|
||||||
|
|
||||||
<p class="w-full border-b accent">Education</p>
|
<p class="w-full border-b accent mt-2">Education</p>
|
||||||
<p>
|
<p>
|
||||||
BS - Computer Science<br />University of Massachusets
|
BS - Computer Science<br />University of Massachusets
|
||||||
Amherset
|
Amherset
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="w-full border-b accent">Passions</p>
|
<p class="w-full border-b accent mt-2">Personal Project</p>
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
href="http://www.solidscribe.com"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
data-v-5eee1041=""
|
||||||
|
data-v-3f0f7299=""
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
id="svg8"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 132.29166 132.29167"
|
||||||
|
height="500"
|
||||||
|
width="500"
|
||||||
|
class="w-4 h-4 accent inline"
|
||||||
|
>
|
||||||
|
<defs data-v-5eee1041="" id="defs2"></defs>
|
||||||
|
<metadata data-v-5eee1041="" id="metadata5">
|
||||||
|
<RDF data-v-5eee1041="">
|
||||||
|
<Work data-v-5eee1041="" rdf:about="">
|
||||||
|
<format data-v-5eee1041="">
|
||||||
|
image/svg+xml
|
||||||
|
</format>
|
||||||
|
<type
|
||||||
|
data-v-5eee1041=""
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
|
||||||
|
></type>
|
||||||
|
<title data-v-5eee1041=""></title>
|
||||||
|
</Work>
|
||||||
|
</RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
data-v-5eee1041=""
|
||||||
|
transform="translate(0,-164.70832)"
|
||||||
|
id="layer1"
|
||||||
|
style="display: inline"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
data-v-5eee1041=""
|
||||||
|
id="path3813-4"
|
||||||
|
d="m 56.22733,165.36641 -55.56249926,15.875 8e-7,63.5 47.62499846,11.90625 v 27.78125 l -47.76066333,-13.9757 0.13566407,10.00695 55.56249926,15.875 v -47.625 l -47.6249985,-11.90625 -8e-7,-47.625 47.7606633,-13.94121 c 0.135664,-2.30629 -0.135664,-9.87129 -0.135664,-9.87129 z"
|
||||||
|
class="darken-accent"
|
||||||
|
style="
|
||||||
|
fill: var(--main-accent);
|
||||||
|
fill-opacity: 1;
|
||||||
|
stroke-linecap: butt;
|
||||||
|
stroke-linejoin: miter;
|
||||||
|
stroke-miterlimit: 4;
|
||||||
|
stroke-dasharray: none;
|
||||||
|
stroke-opacity: 1;
|
||||||
|
"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
data-v-5eee1041=""
|
||||||
|
id="path4563"
|
||||||
|
d="m 20.508581,220.92891 c 15.265814,-14.23899 27.809717,-7.68002 39.687499,3.96875 v -7.9375 C 51.75093,200.8366 37.512584,206.01499 20.508581,205.05391 Z"
|
||||||
|
class="brighten-accent"
|
||||||
|
style="
|
||||||
|
fill: var(--main-accent);
|
||||||
|
fill-opacity: 1;
|
||||||
|
stroke-width: 0.4px;
|
||||||
|
stroke-linecap: butt;
|
||||||
|
stroke-linejoin: miter;
|
||||||
|
stroke-opacity: 1;
|
||||||
|
"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
data-v-5eee1041=""
|
||||||
|
id="path4563-6"
|
||||||
|
d="m 111.78985,220.92891 c -15.265834,-14.23899 -27.809737,-7.68002 -39.68752,3.96875 v -7.9375 c 8.445151,-16.12356 22.683497,-10.94517 39.68752,-11.90625 z"
|
||||||
|
class="brighten-accent"
|
||||||
|
style="
|
||||||
|
display: inline;
|
||||||
|
fill: var(--main-accent);
|
||||||
|
fill-opacity: 1;
|
||||||
|
stroke-linecap: butt;
|
||||||
|
stroke-linejoin: miter;
|
||||||
|
stroke-opacity: 1;
|
||||||
|
"
|
||||||
|
></path>
|
||||||
|
<path
|
||||||
|
data-v-5eee1041=""
|
||||||
|
id="path3813-4-2"
|
||||||
|
d="m 76.07108,165.36641 55.5625,15.875 v 63.5 l -47.625,11.90625 v 27.78125 l 47.76067,-13.9757 -0.13567,10.00695 -55.5625,15.875 v -47.625 l 47.625,-11.90626 V 189.17891 L 75.93542,175.2377 c -0.13567,-2.30629 0.13566,-9.87129 0.13566,-9.87129 z"
|
||||||
|
class="brighten-accent"
|
||||||
|
style="
|
||||||
|
display: inline;
|
||||||
|
fill: var(--main-accent);
|
||||||
|
fill-opacity: 1;
|
||||||
|
stroke-linecap: butt;
|
||||||
|
stroke-linejoin: miter;
|
||||||
|
stroke-miterlimit: 4;
|
||||||
|
stroke-dasharray: none;
|
||||||
|
stroke-opacity: 1;
|
||||||
|
"
|
||||||
|
></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
Solid Scribe</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p>A zero-access encrypted, secure, note taking application.</p>
|
||||||
|
<p>
|
||||||
|
Leverages applied cryptography and web-sockets with a modern
|
||||||
|
responsive design.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Review my work:
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://git.maxg.cc/Max/SolidScribe"
|
||||||
|
>Solid Scribe Source Code</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="w-full border-b accent mt-2">Passions</p>
|
||||||
<p>
|
<p>
|
||||||
Building
|
Building
|
||||||
<a
|
<a href="https://maxg.cc/blog/pc-builds/" target="_blank"
|
||||||
href="http://blog.maxg.cc/2023/02/22/pc-builds/"
|
|
||||||
target="_blank"
|
|
||||||
>PCs</a
|
>PCs</a
|
||||||
>
|
>
|
||||||
&
|
&
|
||||||
<a
|
<a
|
||||||
href="http://blog.maxg.cc/2023/01/11/Build-a-Keyboard-Links/#My-Builds"
|
href="https://maxg.cc/blog/build-a-keyboard-links#my-builds"
|
||||||
>Keyboards</a
|
>Keyboards</a
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
<p>Cooking, Diet, Nutrition</p>
|
<p>Cooking, Diet, Nutrition</p>
|
||||||
<p>Brazilian Jiu-Jitsu, Ultimate Frisbee</p>
|
<p>Brazilian Jiu-Jitsu, Ultimate Frisbee</p>
|
||||||
<p>Coffee Snobbery</p>
|
<p>Coffee Snobbery</p>
|
||||||
|
|
||||||
|
<p class="w-full border-b accent">Social</p>
|
||||||
|
<a
|
||||||
|
href="https://github.com/stimularity"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="h-4 w-4 inline subtle"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
>
|
||||||
|
<defs></defs>
|
||||||
|
<g
|
||||||
|
id="Page-1"
|
||||||
|
stroke="none"
|
||||||
|
stroke-width="1"
|
||||||
|
fill="none"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
id="Dribbble-Light-Preview"
|
||||||
|
transform="translate(-140.000000, -7559.000000)"
|
||||||
|
fill="#52525b"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
id="icons"
|
||||||
|
transform="translate(56.000000, 160.000000)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M94,7399 C99.523,7399 104,7403.59 104,7409.253 C104,7413.782 101.138,7417.624 97.167,7418.981 C96.66,7419.082 96.48,7418.762 96.48,7418.489 C96.48,7418.151 96.492,7417.047 96.492,7415.675 C96.492,7414.719 96.172,7414.095 95.813,7413.777 C98.04,7413.523 100.38,7412.656 100.38,7408.718 C100.38,7407.598 99.992,7406.684 99.35,7405.966 C99.454,7405.707 99.797,7404.664 99.252,7403.252 C99.252,7403.252 98.414,7402.977 96.505,7404.303 C95.706,7404.076 94.85,7403.962 94,7403.958 C93.15,7403.962 92.295,7404.076 91.497,7404.303 C89.586,7402.977 88.746,7403.252 88.746,7403.252 C88.203,7404.664 88.546,7405.707 88.649,7405.966 C88.01,7406.684 87.619,7407.598 87.619,7408.718 C87.619,7412.646 89.954,7413.526 92.175,7413.785 C91.889,7414.041 91.63,7414.493 91.54,7415.156 C90.97,7415.418 89.522,7415.871 88.63,7414.304 C88.63,7414.304 88.101,7413.319 87.097,7413.247 C87.097,7413.247 86.122,7413.234 87.029,7413.87 C87.029,7413.87 87.684,7414.185 88.139,7415.37 C88.139,7415.37 88.726,7417.2 91.508,7416.58 C91.513,7417.437 91.522,7418.245 91.522,7418.489 C91.522,7418.76 91.338,7419.077 90.839,7418.982 C86.865,7417.627 84,7413.783 84,7409.253 C84,7403.59 88.478,7399 94,7399"
|
||||||
|
id="github-[#142]"
|
||||||
|
></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
GitHub
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="http://www.maxg.cc"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<IdentificationIcon class="h-4 w-4 inline subtle" />
|
||||||
|
Personal
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Additional Meta -->
|
||||||
|
<div v-if="false" class="w-full do-not-print">
|
||||||
|
<h1 class="py-2 font-bold">Additional Data - Resume SEO</h1>
|
||||||
|
<p>
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
I'm a Front End, Web Developer, Full Stack, Backend,
|
||||||
|
Coding, Maintaining, Optimizing, Marketing web
|
||||||
|
properties, High-visibility projects, Autonomy, Exciting
|
||||||
|
new tools, Technologies, Collaboration, Creative team,
|
||||||
|
Novel solutions, Web development problems, Latest
|
||||||
|
techniques, Web standards, Accessibility, Best
|
||||||
|
practices, Experimenting, Self-starter, Optimistic,
|
||||||
|
Resourceful, Flexible, Creative team, Challenging, Up to
|
||||||
|
date, A/B testing, Analytics integration, WordPress,
|
||||||
|
Plug-ins, Usability, Salesforce, Product Marketing,
|
||||||
|
SEO/SEM best practices, Corporate marketing sites,
|
||||||
|
Content management systems, Problem-Solver, Innovative,
|
||||||
|
Team Player, Collaborative, Analytical, Detail-Oriented,
|
||||||
|
Results-Driven, Adaptable, Self-Motivated, Continuous
|
||||||
|
Learner, Proactive, Efficient, Communicative, Critical
|
||||||
|
Thinker, Technical Proficiency, Creative Thinker,
|
||||||
|
Resourceful, Quality-Focused, ChatGPT to write code,
|
||||||
|
Large language model using, type of person.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
I use Large Language Models and Artificial Intelligence
|
||||||
|
to increase my productivity and correctness when writing
|
||||||
|
code. Acronym Expansions: Hyper Text Markup Language,
|
||||||
|
Javascript, User Interface, User Experience, Cascading
|
||||||
|
Style Sheets, MySQL Database, Version Control Git,
|
||||||
|
Continuous integration, Continuous development, Object
|
||||||
|
Oriented Design, Model View Controller, Application
|
||||||
|
Program Interface, Software as a Service, Business to
|
||||||
|
Business, Bachelors Degree, General Data Protection
|
||||||
|
Regulation, Object Relational Mapper
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ChevronRightIcon class="w-3 h-3 accent inline" />
|
||||||
|
Resume Generated from
|
||||||
|
<a href="https://www.maxg.cc">www.maxg.cc</a>
|
||||||
|
Which was built using Vue3, Nuxt hosted locally on my
|
||||||
|
dev server, using PM2 and Nitro. Accessed via Cloudflare
|
||||||
|
Zero-Trust Tunnels.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- pagebreak for pdf -->
|
<!-- pagebreak for pdf -->
|
||||||
<div class="pagebreak"></div>
|
<div v-if="false" class="pagebreak"></div>
|
||||||
|
|
||||||
<div class="w-fill p-4 pb-10 flex justify-center">
|
<div class="w-fill py-12 flex justify-center items-center no-print">
|
||||||
<a
|
<a
|
||||||
href="/resume.pdf"
|
href="/resume.pdf"
|
||||||
class="flex flex-row border border-zinc-200 shadow-lg rounded-md px-4 py-2 bg-white"
|
class="flex flex-row border border-zinc-200 shadow-lg rounded-md px-4 py-2 bg-white"
|
||||||
@ -296,6 +668,7 @@
|
|||||||
<p class="text-zinc-500 text-xs">.PDF Format</p>
|
<p class="text-zinc-500 text-xs">.PDF Format</p>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
<p class="text-zinc-500 p-4">or (CTRL + P)</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="false">
|
<div v-if="false">
|
||||||
@ -307,7 +680,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- headshot and overview -->
|
<!-- headshot and overview -->
|
||||||
<div class="w-full bg-gradient-to-tr from-slate-100 to-teal-50">
|
<div
|
||||||
|
class="w-full bg-gradient-to-tr from-slate-100 to-teal-50 no-print"
|
||||||
|
>
|
||||||
<div class="w-full md:max-w-5xl m-auto flex flex-row flex-wrap">
|
<div class="w-full md:max-w-5xl m-auto flex flex-row flex-wrap">
|
||||||
<!-- info and downloads -->
|
<!-- info and downloads -->
|
||||||
<div class="w-6/12 flex flex-col justify-center">
|
<div class="w-6/12 flex flex-col justify-center">
|
||||||
@ -324,16 +699,25 @@
|
|||||||
<div class="p-4"></div>
|
<div class="p-4"></div>
|
||||||
|
|
||||||
<div class="pl-4">
|
<div class="pl-4">
|
||||||
<p>Dig Deeper</p>
|
<p class="text-zinc-500">Dig a little Deeper</p>
|
||||||
<p>
|
<p class="py-4 pl-1">
|
||||||
Connect with me on Linkedin
|
<NuxtLink
|
||||||
|
to="/blog/proudest-software-engineering-achievements"
|
||||||
|
>
|
||||||
|
<CursorArrowRippleIcon
|
||||||
|
class="w-6 h-6 accent inline"
|
||||||
|
/>
|
||||||
|
A few of my proudest engineering achievements
|
||||||
|
</NuxtLink>
|
||||||
|
</p>
|
||||||
|
<p class="pl-1">
|
||||||
<a
|
<a
|
||||||
href="https://www.linkedin.com/in/max-g-856a2555"
|
href="https://www.linkedin.com/in/max-g-856a2555"
|
||||||
>
|
>
|
||||||
<CursorArrowRippleIcon
|
<CursorArrowRippleIcon
|
||||||
class="w-8 h-8 accent inline"
|
class="w-6 h-6 accent inline"
|
||||||
/>
|
/>
|
||||||
Linkedin
|
Connect with me on Linkedin
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -357,7 +741,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- marketing box -->
|
<!-- marketing box -->
|
||||||
<div class="w-full bg-slate-200">
|
<div class="w-full bg-slate-200 no-print">
|
||||||
<div class="p-4 w-full md:max-w-5xl m-auto pt-10">
|
<div class="p-4 w-full md:max-w-5xl m-auto pt-10">
|
||||||
<h1 class="text-3xl">Personal Projects</h1>
|
<h1 class="text-3xl">Personal Projects</h1>
|
||||||
<p class="text-zinc-500">
|
<p class="text-zinc-500">
|
||||||
@ -366,7 +750,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row flex-wrap">
|
<div class="flex flex-row flex-wrap no-print">
|
||||||
<div class="w-full bg-slate-200 pb-10">
|
<div class="w-full bg-slate-200 pb-10">
|
||||||
<div
|
<div
|
||||||
class="flex flex-row flex-wrap items-stretch justify-around max-w-none md:max-w-5xl m-auto"
|
class="flex flex-row flex-wrap items-stretch justify-around max-w-none md:max-w-5xl m-auto"
|
||||||
@ -412,7 +796,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full overflow-hidden relative bg-black">
|
<div class="w-full overflow-hidden relative bg-black no-print">
|
||||||
<div
|
<div
|
||||||
class="w-full md:max-w-5xl m-auto flex flex-row flex-wrap z-20"
|
class="w-full md:max-w-5xl m-auto flex flex-row flex-wrap z-20"
|
||||||
>
|
>
|
||||||
@ -430,7 +814,7 @@
|
|||||||
<div
|
<div
|
||||||
class="w-8/12 md:w-6/12 flex flex-col justify-center items-start text-white pl-5"
|
class="w-8/12 md:w-6/12 flex flex-col justify-center items-start text-white pl-5"
|
||||||
>
|
>
|
||||||
<p class="text-xl md:text-3xl font-bold pb-5">
|
<p class="text-xl md:text-3xl font-bold text-sm pb-6">
|
||||||
Lets Chat. Anytime. Anywhere.
|
Lets Chat. Anytime. Anywhere.
|
||||||
</p>
|
</p>
|
||||||
<div class="border-l-4 border-l-zinc-600 pl-4">
|
<div class="border-l-4 border-l-zinc-600 pl-4">
|
||||||
@ -444,7 +828,7 @@
|
|||||||
(480) 788-5217
|
(480) 788-5217
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4"></div>
|
<div class="p-5"></div>
|
||||||
<div class="border-l-4 border-l-zinc-600 pl-4">
|
<div class="border-l-4 border-l-zinc-600 pl-4">
|
||||||
<p>Email me and schedule a meeting</p>
|
<p>Email me and schedule a meeting</p>
|
||||||
<EnvelopeIcon class="h-4 w-4 inline" />
|
<EnvelopeIcon class="h-4 w-4 inline" />
|
||||||
@ -465,6 +849,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BeakerIcon,
|
BeakerIcon,
|
||||||
MapPinIcon,
|
MapPinIcon,
|
||||||
@ -474,6 +860,7 @@
|
|||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
FolderArrowDownIcon,
|
FolderArrowDownIcon,
|
||||||
CursorArrowRippleIcon,
|
CursorArrowRippleIcon,
|
||||||
|
IdentificationIcon,
|
||||||
} from "@heroicons/vue/24/outline";
|
} from "@heroicons/vue/24/outline";
|
||||||
|
|
||||||
const projects = [
|
const projects = [
|
||||||
@ -515,7 +902,36 @@
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let generalView = ref(true);
|
||||||
|
let frontEndView = ref(false);
|
||||||
|
let verboseView = ref(false);
|
||||||
|
|
||||||
|
function toggleResumeView() {
|
||||||
|
console.log(generalView.value);
|
||||||
|
if (generalView.value) {
|
||||||
|
generalView.value = false;
|
||||||
|
frontEndView.value = true;
|
||||||
|
verboseView.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (frontEndView.value) {
|
||||||
|
generalView.value = false;
|
||||||
|
frontEndView.value = false;
|
||||||
|
verboseView.value = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (verboseView.value) {
|
||||||
|
generalView.value = true;
|
||||||
|
frontEndView.value = false;
|
||||||
|
verboseView.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
// Set Page title
|
||||||
|
document.title = "Max Gialanella | Resume";
|
||||||
|
|
||||||
// generate stars
|
// generate stars
|
||||||
function randomNumber(min, max) {
|
function randomNumber(min, max) {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
@ -546,6 +962,7 @@
|
|||||||
--primary-color: #d0b24d;
|
--primary-color: #d0b24d;
|
||||||
--color-hint: #515151;
|
--color-hint: #515151;
|
||||||
--border: #ccc;
|
--border: #ccc;
|
||||||
|
--main-accent: rgb(82, 82, 91);
|
||||||
|
|
||||||
--duration: 30;
|
--duration: 30;
|
||||||
--rp1: 20;
|
--rp1: 20;
|
||||||
@ -652,7 +1069,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.paper {
|
.paper {
|
||||||
background: #fff;
|
|
||||||
box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.15), 0 -10px 0 -5px #eee,
|
box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.15), 0 -10px 0 -5px #eee,
|
||||||
0 -10px 1px -4px rgba(0, 0, 0, 0.15), 0 -20px 0 -10px #eee,
|
0 -10px 1px -4px rgba(0, 0, 0, 0.15), 0 -20px 0 -10px #eee,
|
||||||
0 -20px 1px -9px rgba(0, 0, 0, 0.15);
|
0 -20px 1px -9px rgba(0, 0, 0, 0.15);
|
||||||
@ -689,6 +1105,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p + p {
|
||||||
|
@apply pt-2;
|
||||||
|
}
|
||||||
|
|
||||||
.d1 {
|
.d1 {
|
||||||
animation-delay: 0.4s;
|
animation-delay: 0.4s;
|
||||||
}
|
}
|
||||||
@ -696,8 +1116,15 @@
|
|||||||
animation-delay: 0.8s;
|
animation-delay: 0.8s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.do-not-print {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* styles for printing as pdf */
|
/* styles for printing as pdf */
|
||||||
@media print {
|
@media print {
|
||||||
|
.main-body {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
.pagebreak {
|
.pagebreak {
|
||||||
page-break-before: always;
|
page-break-before: always;
|
||||||
}
|
}
|
||||||
@ -705,5 +1132,18 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
}
|
}
|
||||||
|
.no-print {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.do-not-print,
|
||||||
|
.do-not-print p,
|
||||||
|
.do-not-print a,
|
||||||
|
.do-not-print .accent {
|
||||||
|
font-size: 9px;
|
||||||
|
opacity: 1;
|
||||||
|
display: inline-block;
|
||||||
|
color: white !important;
|
||||||
|
background-color: white !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
BIN
public/keyboards/anotheratreyu.jpg
Normal file
After Width: | Height: | Size: 199 KiB |
BIN
public/keyboards/argumentforergo.jpg
Normal file
After Width: | Height: | Size: 270 KiB |
BIN
public/keyboards/atreyucomplete.jpg
Normal file
After Width: | Height: | Size: 382 KiB |
BIN
public/keyboards/atreyunocaps.jpg
Normal file
After Width: | Height: | Size: 278 KiB |
BIN
public/keyboards/atreyupcb.jpg
Normal file
After Width: | Height: | Size: 207 KiB |
BIN
public/keyboards/atreyuvariuswitches.jpg
Normal file
After Width: | Height: | Size: 382 KiB |
BIN
public/keyboards/completeatreyu.jpg
Normal file
After Width: | Height: | Size: 175 KiB |
BIN
public/keyboards/lillybanner.jpg
Normal file
After Width: | Height: | Size: 108 KiB |
BIN
public/keyboards/lilyandatreyu.jpg
Normal file
After Width: | Height: | Size: 657 KiB |
BIN
public/keyboards/zmkconfig.png
Normal file
After Width: | Height: | Size: 16 KiB |