Skip to content

Commit

Permalink
✨ [FEAT] 10-29-2024 Update
Browse files Browse the repository at this point in the history
  • Loading branch information
domogami committed Oct 29, 2024
1 parent 2fef4b9 commit 261f0d7
Show file tree
Hide file tree
Showing 37 changed files with 4,581 additions and 4 deletions.
56 changes: 56 additions & 0 deletions content/Blog Posts/Automating Obsidian Publish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: Automating Obsidian Publish
---

## Script

To make it easier for me to keep my website up to date with my personal vault, I needed to automate the publish process. Below is a script I can trigger from RayCast in order to quickly update my website with a simple trigger and confirmation key.

````bash
#!/bin/bash

# Remove Old Files
trash /Users/dom/Documents/GitHub/obsidian-site/quartz/content/*
trash /Users/dom/Documents/GitHub/obsidian-site/quartz/public/*

# Export my Obsidian Vault to the GitHub content folder
/Users/dom/Documents/GitHub/obsidian-site/obsidian-export/target/debug/obsidian-export --frontmatter=always ~/Library/Mobile\ Documents/iCloud~md~obsidian/Documents/Dom\'s\ 2nd\ Brain/ /Users/dom/Documents/GitHub/obsidian-site/quartz/content

# Compile Quartz Site
cd /Users/dom/Documents/GitHub/obsidian-site/quartz
npx quartz build

# Save today's date for the commit name
date=$(date '+%m-%d-%Y')

# Output current changed files
OUTPUT="$(git status)"
echo "${OUTPUT}"

# A helper function to ask for confirmation
asksure() {
echo -n "Are you sure (Y/N)? "
while read -r -n 1 -s answer; do
if [[ $answer = [YyNn] ]]; then
[[ $answer = [Yy] ]] && retval=0
[[ $answer = [Nn] ]] && retval=1
break
fi
done

echo # just a final linefeed, optics...

return $retval
}

if asksure; then
# Publish!
git add .
git commit -m "✨ [FEAT] $date Update"
git push

echo "Published! 🚀"
else
echo "Aborting! ❌"
fi
````
144 changes: 144 additions & 0 deletions content/Blog Posts/First Blog Post.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
title: My First Blogpost
tags:
- Blog
---

# My First Blogpost

Hey, my name is Dom and I am a recent Mathematics - Computer Science college graduate from UCSD working as a Software Engineer. Last summer, I had the pleasure of interning at Amazon where I had the opportunity to not only expand my skills but also learn what it is like to be a Software Engineer.

From my experience, Software Engineering is a job centered around constantly learning. As someone who loves going down rabbit-holes and learning about tech in my free time, I have found that I am a perfect fit for this line of work. Although I am sure many people would find this field draining and a constant uphill battle. Acknowledging never ending challenges as one of the key components of being a successful Software Engineer has led me to create this blog which will serve as my own personal knowledge bank as I continue to learn throughout my career.

This first post will center around creating the blog that you are reading this post on right now (if this is still my original blog). It is built using Remix.js which is a new web technology that allows for better routing and faster load times. I chose this technology because it is similar to Next.js but has many added benefits including better form handling with "action loaders" and component error bounds which can display a special UI element for a component that fails to render without crashing the entire page. I first heard about this technology from a coworker on my team at Amazon and decided to give it a shot. What I didn't realize was how many unexpected errors would arise from the decision to build with Remix.js.

## The Easy Part

After completing a wonderful Remix.js tutorial blog and following a tutorial by [Chris Benjamin](https://github.com/cbenjamin2009/remix-blog) I felt confident to create a new Remix project using MongoDB as a backend along with Prisma to interact with the database. This part went surprisingly well and I was able to create not only the routes but also set up SCSS for styling which compiles to CSS in an output directory. As someone who as developed many static sites with no backend, I find frontend development and styling very natural and have memorized nearly all of the SCSS properties necessary to build a webpage that looks decent with a distinct style. I have finally gotten to the point where I can go from idea to implementation with very little friction. The same cannot be said for my backend experience.

## Choosing an Editor

Once I began brainstorming and designing the backend for my blog I began realizing that I want an easy way to edit and type up new blogposts and that I needed an Admin page to do this. I began by looking into live markdown compilers for websites similar to embedding something like Obsidian or markdown into an edit page. After a bit of research I fell in love with [Editor.js](https://editorjs.io/) which is an open source block editor that felt very similar to Notion which is what I used throughout my senior year of college. I decided that this was perfect and decided to embed it into my edit-blog-post page. I would love to say that this was an easy task but unfortunately this is where my decision to develop with Remix began testing my patience. Editor.js does not work well with SSR at the moment and I found many posts with similar [issues](https://github.com/Jungwoo-An/react-editor-js/issues/58) regarding the 'window' being undefined. Sadly, it seemed that Next.js has a larger community than Remix.js and it took me quite some time to find the solution to this problem. To get around the server side rendering issues with Editor.js on Remix I had to do the following

````tsx
import EditorJS from '~/editorjs.client.tsx';
import { ClientOnly } from 'remix-utils';

// Component rendering Editorjs
export default function Editor() {
return (
<ClientOnly>
{() => <EditorJS />}
</ClientOnly>
);
}
````

Using the ClientOnly component from remix-utils and naming the editor component file with the extension `.client.tsx` ended up solving the issue for me. Editor.js cannot currently be rendered on the server so it must be rendered on the client side in order to work as expected. With the editor working I thought that finally the rest would be smooth sailing but alas, I had only just begun.

## Images with S3

One of the features that I believed my blog needed to have was the ability to have images embedded within each post. What good is a blog about the things that I learn if I cannot make use of visual aids and images to better convey my messages. I turned to my friend Shravan to ask how best to store images using MongoDB and to my dismay I found that Mongo was not the best way to store images. Instead, it is better to use a middleware tool like Multer in coordination with an S3 storage bucket which is a better way to store files and images. MongoDB then stores the URL to the uploaded photo. Unfortunately this is another pain point for Remix.js that I did not realize before I decided to embark on this painful journey.

## Problems with Multer

Multer is a middleware that allows a file to be downloaded by the server side of an application and stored locally then uploaded to a cloud service like AWS S3. Unfortunately because Remix does not have the request and response objects of Node/Connect/Express there is no way to run Multer and it is very difficult to run middleware or an Express server because Remix itself is an express server. Not being able to use Multer made things quite challenging and I ended up needing to upload everything to S3 directly. Additionally because I was having issues with 64 bit filestreams, I ended up creating a Netlify function (very similar to an AWS Lambda Function) that generates a unique upload link that I can use from the frontend to directly upload the file. This ended up being extremely useful because now with one function I can upload an image and as a response the public URL is returned.

## Editor.js to HTML

Now that I am able to successfully upload images it is time to bring it all together. I stumbled across a library that allows editor.js to be converted to HTML, elegantly named [editors-html](https://www.npmjs.com/package/editorjs-html), which gives me full control to style each component of each blogpost.

After a bit of front end witchcraft and tedious styling, my blog was finally coming together, but before I could write any blogposts, I decided that there needed to be a color scheme that supports light mode and dark mode.

## Color scheme

For this site, I wanted to have a light mode and a dark mode for greater flexibility and a more functional UX. I also wanted the theme to span the entire website and be loaded in from the browsers memory to preserve dark mode every time you visit the site.

I ended up wrapping the entire application in a ThemeProvider component that changes the background and color css properties according to the selected theme.

````tsx
const ThemeProvider = (props) => {
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<div className={`theme--${props.theme}`}>{props.children}</div>
</ThemeContext.Provider>
);
};
````

The following scss code creates a mixin that can be used across scss files to add a custom theme-specific style to specified components.

````scss
@mixin themed() {
@each $theme, $map in $themes {
.theme--#{$theme} & {
$theme-map: () !global;
@each $key, $submap in $map {
$value: map-get(map-get($themes, $theme), '#{$key}');
$theme-map: map-merge(
$theme-map,
(
$key: $value,
)
) !global;
}
@content;
$theme-map: null !global;
}
}
}

@function t($key) {
@return map-get($theme-map, $key);
}
````

Next, create the themes

````scss
$themes: (
Light: (
bg: $bg--light,
text: $text--light,
border: 1px solid $text--light,
g: $green--light,
b: #61afef,
r: #e06c75,
p: #e5c07b,
y: #c678dd,
),
Dark: (
bg: $bg--dark,
text: $text--dark,
border: 1px solid $text--dark,
g: $green--dark,
b: #61afef,
r: #e06c75,
p: #c678dd,
y: #e5c07b,
),
);
````

After adding this piece of code, all that is left is to theme each component according to the `themed()` property as shown below.

````scss
.exampleClass {
@include themed() {
background-color: t('g');
}
}
````

# Conclusion

After all of this work, there is still so much left to do. I have yet to do the following:

### Todo

* [ ] Mobile Support
* [ ] Color Scheme flash bug
* [ ] Better Post Query Support
* [ ] Post Search Function

However, despite this blog not being complete, I have already learned so much about not only Remix but also React in general and SCSS. I also got very distracted by my new obsession with neovim and ricing MacOS. The only thing left is to write some actual blogposts and it seems my first one is just about finished.
11 changes: 11 additions & 0 deletions content/Blog Posts/Window Manager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: Window Manager
---

## Yabai

I use a window manager called [Yabai](../Side%20Projects/Blog%20Redesign/Yabai.md) on my work computer and I have spoken highly of it in the past. I use a 2019 Intel MacBook Pro at my full time job which is prone to overheating and poor performance when running anything beyond IntelliJ. For this reason, I've found Yabai to be the most performant and best overall option despite it's shortcomings. Most notably, Yabai does not allow near-instant space switching without disabling SIP, which most certainly cannot be done on a work machine managed by an organization.

## Aerospace

I have recently switched to Aerospace as my window manager because of a YouTube recommendation from [Josean Martinez](https://www.youtube.com/@joseanmartinez) and [Ben Vallack](https://www.youtube.com/@BenVallack). I was excited for an alternative that was so similar to Yabai but praised for being better. I was intrigued by the accordion style window layout but was pleasantly surprised with how often I found myself using it. This is absolutely the best option that I have found so far and I definitely recommend Josean's tutorial for setup and feature walkthrough!
84 changes: 84 additions & 0 deletions content/Books/Clean Code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
title: Clean Code
tags:
- Code
---

# Introduction

It is the job of the developer, not the manager to defend clean code and insist on writing code that will not require additional maintenance over time. The manager should be focused on meeting deadlines and scheduling while the developer should insist on doing things correctly without taking shortcuts because it is in fact the fastest way to meet a deadline. While it may seem like taking more time to write cleaner code would take longer than writing code quickly, over the long run hastily written code consumes more time and requires more maintenance which will result in a greater number of missed deadlines.

>
> Leave the campground cleaner than you found it. - Boy Scouts
# Meaningful Names

## Use Intention Revealing Names

Names of variables, methods, and classes should avoid being implicit and should have easily identifiable names that explicitly state what the piece of code is doing, why it exists, and how to use it. If all cannot be achieved then a comment may be necessary.

### Implicit Code

````c++
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
````

### Explicit Code

````c++
public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard)
if (cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}
````

### Explicit with Classes

````c++
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
````

## Avoid Disinformation

* Never name pieces of code using keywords that are not reflective of what you are describing. i.e do not label a group of accounts `AccountList` unless it is actually a list.
* Avoid similarly shaped names, or names that are too close to one another
* Avoid using lowercase L and capital o, as l looks like 1 and O looks like 0

## Make Meaningful Distinctions (I am guilty...)

It can be tempting to satisfy the compiler at times without considering the long term consequences of your decision. It is bad practice to change only a single letter or number when encountering an error to make compiler errors go away. Avoid meaningless and redundant words like "data" vs "info" which can be indistinct in some contexts. Also avoid naming similar to the example below:

````c++
getActiveAccount();
getActiveAccounts();
getActiveAccountInfo();
````

## Make Searchable Names

Avoid using numbers in names because it can be hard to search for. Also avoid names that are too short and contain commonly used letters like 'e.'
One rule of thumb is:

>
> The length of a name should correspond to the size of its scope
## Prefixes

Because classes are much smaller than they used to be and compilers have become so much smarter, prefixes are not necessary and just cause clutter. Prefer `ShapeFactoryImp` for implementation over `IShapeFactory` or `CShapeFactroy`

## Avoid Mental Mappings
Loading

0 comments on commit 261f0d7

Please sign in to comment.