Skip to content

Commit 0b537d0

Browse files
committed
Add Jekyll build and deploy workflow
1 parent 644df93 commit 0b537d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1695
-7
lines changed

_config.yml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ theme: jekyll-theme-chirpy
99
lang: en
1010

1111
# Change to your timezone › https://kevinnovak.github.io/Time-Zone-Picker
12-
timezone:
12+
timezone: America/Chicago
1313

1414
# jekyll-seo-tag settings › https://github.com/jekyll/jekyll-seo-tag/blob/master/docs/usage.md
1515
# ↓ --------------------------
1616

17-
title: Chirpy # the main title
17+
title: Blog of Tom # the main title
1818

19-
tagline: A text-focused Jekyll theme # it will display as the subtitle
19+
tagline: Ramblings of an old Dev Ops guy # it will display as the subtitle
2020

2121
description: >- # used by seo meta and the atom feed
2222
A minimal, responsive and feature-rich Jekyll theme for technical writing.
@@ -34,7 +34,7 @@ twitter:
3434
social:
3535
# Change to your full name.
3636
# It will be displayed as the default author of the posts and the copyright owner in the Footer
37-
name: your_full_name
37+
name: Thomas Sloan
3838
email: example@domain.com # change to your email address
3939
links:
4040
# The first element serves as the copyright owner's link
@@ -98,7 +98,7 @@ theme_mode: # [light | dark]
9898
cdn:
9999

100100
# the avatar on sidebar, support local or CORS resources
101-
avatar:
101+
avatar: assets/img/my-profile-pic.jpg
102102

103103
# The URL of the site-wide social preview image used in SEO `og:image` meta tag.
104104
# It can be overridden by a customized `page.image` in front matter.
@@ -170,6 +170,10 @@ collections:
170170
tabs:
171171
output: true
172172
sort_by: order
173+
tutorials:
174+
output: true
175+
sort_by: order
176+
permalink: /:collection/:path/:title
173177

174178
defaults:
175179
- scope:
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
title: Creating a API for Jekyll
3+
excerpt: "Jekyll is static, but that doesn't mean you can't interact with it."
4+
categories: ["Software","Jekyll"]
5+
tags:
6+
- jekyll
7+
- api
8+
---
9+
10+
One thing I miss about [Ghost](https://ghost.org/) is the full REST API it had. I used API with n8n to build a workflow that would retrieve draft posts and run them through OpenAI looking for spelling and grammar mistakes. It would even strip code blocks out, so you were only sending the bare minimum text to the OpenAI helping to keep costs down.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
title: "How 1Password CLI Changed the Way I Secure My PowerShell Scripts"
3+
date: 2025-10-09 10:00:00 -0600
4+
categories: [Automation, Security]
5+
tags: [PowerShell, 1Password, CLI, DevOps, Scripting]
6+
description: >
7+
I’ve written my fair share of PowerShell scripts over the years, but it wasn’t until I stumbled onto 1Password’s CLI that I stopped worrying about where my secrets were hiding.
8+
image:
9+
path: /assets/img/1password-post.webp
10+
alt: "1Password CLI and PowerShell automation"
11+
---
12+
13+
I’ve written a lot of PowerShell scripts over the years—some for quick fixes, others that still run in production today. And like most people, I’ve had moments where convenience won out over best practice. Hard coding a password “just this once,” or dropping an API key into an environment variable because it was easier than setting up something more secure. It worked… until I started thinking about what could happen if one of those scripts ever leaked. That’s when I found [1Password’s CLI](https://developer.1password.com/docs/cli), and it completely changed how I handle credentials in my automation.
14+
15+
### Why Hardcoding or Env Vars Aren’t Safe
16+
17+
I won’t lie—using environment variables or plaintext passwords in scripts feels easy at first. You don’t need to think much, and your automation “just works.” But convenience comes at a cost:
18+
19+
- **Accidental leaks:** Sharing scripts via email, GitHub, or Slack could expose sensitive credentials.
20+
- **Human error:** Forgetting to rotate credentials or cleaning up temporary variables is all too easy.
21+
- **Security audits:** Plaintext secrets are a compliance nightmare in many organizations.
22+
23+
Every time I reviewed old scripts, I cringed a little at what I had left lying around. That’s when I realized I needed a better approach—one that was both **secure and automated**.
24+
25+
### Enter 1Password CLI
26+
27+
The 1Password Command Line Interface (CLI) lets you interact with your 1Password vault directly from scripts. No more hardcoding, no more risky environment variables. Instead, you can:
28+
29+
- Retrieve credentials on the fly with PowerShell.
30+
- Keep all secrets in one secure, audited location.
31+
- Integrate seamlessly into CI/CD pipelines or automation scripts.
32+
33+
For example, in PowerShell, you can fetch a login like this:
34+
35+
```powershell
36+
# Get a stored item from your vault
37+
$apiKey = op item get "My API Key" --field "password"
38+
```
39+
40+
Suddenly, your scripts are safe by default, and you don’t have to remember to rotate secrets manually—they’re stored securely in 1Password.
41+
42+
> This works for interactive scripts, or scripts that you physically start. For unattended automations and scripts that you want
43+
> to run on a schedule, you need to use a [1Password Service Account](https://developer.1password.com/docs/service-accounts/) or
44+
> a [1Password Connect Server](https://developer.1password.com/docs/connect/).
45+
{: .prompt-info}
46+
47+
### Benefits I’ve Seen
48+
49+
Since switching to 1Password CLI in my scripts, I’ve noticed several real-world improvements:
50+
51+
- **Peace of mind**: No more wondering if I accidentally left a password exposed.
52+
53+
- **Easier collaboration**: Team members can run scripts without sharing secrets directly.
54+
55+
- **Auditing and compliance**: 1Password keeps logs of who accessed what and when.
56+
57+
- **Flexibility**: You can still automate anything without compromising security.
58+
59+
It’s a small change that makes a big difference in how I approach scripting and automation.
60+
61+
>**BONUS** - VS Code is my editor of choice for all my scripting. There is a super awesome [1Password for VS Code plugin](https://developer.1password.com/docs/vscode/) for it!
62+
{: .prompt-tip}
63+
64+
### My Workflow
65+
66+
Here’s a simplified version of how I use it in day-to-day scripting:
67+
68+
1. Store sensitive credentials in 1Password vaults.
69+
70+
2. Use the CLI to fetch credentials at runtime.
71+
72+
3. Never store secrets locally in scripts or environment variables.
73+
74+
4. Rotate credentials in 1Password as needed—scripts automatically pick up the latest values.
75+
76+
This workflow keeps both my scripts and my sanity intact.
77+
78+
### Final Thoughts
79+
80+
I’ve learned the hard way that convenience can be costly when it comes to secrets. Hardcoding passwords or using environment variables might feel fine today, but they’re a ticking time bomb for tomorrow. 1Password CLI has become an essential part of my PowerShell toolkit, letting me automate securely without compromise.
81+
82+
If you’re still embedding credentials in your scripts, give [1Password CLI](https://developer.1password.com/docs/cli) a try. It might just change the way you think about automation, like it did for me.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
title: Streamlining Task Management with Todoist and Outlook
3+
description: How I use Todoist, Outlook, and a little bit of PowerShell to get all my meetings into Todoist.
4+
image: https://images.unsplash.com/photo-1649433391719-2e784576d044?q=80&w=1471&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D
5+
categories: [Automation]
6+
tags: [Todoist,PowerShell,Outlook]
7+
---
8+
9+
I have been using Todoist to manage all my day-to-day tasks and meetings. It's an integral part of my routine, and to maximize its utility, I've been incorporating all my calendar events and meetings into it. Like many people, I use a Google calendar for personal and family events and an Outlook calendar for work-related events. While Google calendar easily syncs with Todoist, the challenge arose when I wanted to sync my Outlook calendar with Todoist, as it only allows syncing with one calendar at a time. Some workarounds involve subscribing to different calendars within one platform, but this wasn't an ideal solution for me.
10+
11+
12+
## Extracting Meetings from Outlook
13+
The first hurdle was figuring out how to extract meetings from Outlook. The official Microsoft Graph API provides some endpoints for working with Outlook. However, it requires setting up an Azure Application, which I don't have the access to do at work (though I did manage to set it up in my personal environment).
14+
After some research, I found an old article that explained how to use PowerShell to access the Outlook desktop client through the Outlook API. This method is a bit outdated and necessitates the use of the Outlook desktop client, but it avoids the need for Azure App permissions or the need to deal with OAuth just to extract your meetings.
15+
16+
17+
## The PowerShell Script
18+
I've developed a PowerShell script to streamline this process. Although it's a work in progress and could use some polishing, it's been effectively serving its purpose. The script achieves the following:
19+
Connects to your Outlook desktop client.
20+
Retrieves all your upcoming meetings for the next 7 days.
21+
Connects to Todoist.
22+
Pulls all your tasks for the next 7 days.
23+
Compares each Outlook meeting with Todoist tasks, and if a task with the same name as the Outlook meeting is not found, it creates one in Todoist.

_layouts/custom/tutorials.html

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
layout: default
3+
refactor: true
4+
---
5+
{% include lang.html %}
6+
7+
<style>
8+
.posts-grid {
9+
display: grid;
10+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
11+
gap: 2rem;
12+
margin: 2rem 0;
13+
}
14+
15+
.post {
16+
background: #fafafa;
17+
border: 1px solid #e2e2e2;
18+
padding: 1rem;
19+
border-radius: 8px;
20+
transition: transform 0.2s ease;
21+
}
22+
23+
.post:hover {
24+
transform: translateY(-4px);
25+
}
26+
.shimmer::before{
27+
background:none;
28+
}
29+
</style>
30+
31+
<h1>Tutorials</h1>
32+
33+
<p>Welcome to my toutorials page.</p>
34+
35+
<img src='/assets/img/power-automate-101-banner.svg'/>
36+
<p>Welcome to <b>Power Automate 101</b> — your step-by-step guide to getting started with automation. In this series, you’ll learn how flows work, how to trigger them,
37+
and how to connect to services like SharePoint, Outlook, and even popular third-party apps. You’ll also explore how to use conditions, manage variables,
38+
and build powerful automations to simplify your daily tasks.</p>
39+
<section class="posts-grid">
40+
{% for post in site.tutorials %}
41+
<article class="post" >
42+
<img src='/assets/img/power-automate-101-banner-02.svg'/>
43+
<h3>
44+
<a href="{{ post.url | relative_url }}">{{ post.title }}</a>
45+
</h3>
46+
{% if post.date %}
47+
<p class="post-date">{{ post.date | date: '%B %d, %Y' }}</p>
48+
{% endif %}
49+
<p>{{ post.excerpt | strip_html | truncate: 160 }}</p>
50+
</article>
51+
{% endfor %}
52+
</section>
53+
<hr/>
54+
<div>
55+
<img src='/assets/img/node-red-banner.svg'/>
56+
<p><i>Comming Soon...</i></p>
57+
</div>
58+
59+
<!-- #post-list -->
60+
61+
{% if paginator.total_pages > 1 %}
62+
{% include post-paginator.html %}
63+
{% endif %}

_layouts/json.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
layout: none
3+
---
4+
[
5+
{% for post in site.posts %}
6+
{
7+
"title": {{ post.title | jsonify }},
8+
"url": {{ post.url | jsonify }},
9+
"date": {{ post.date | date_to_string | jsonify }},
10+
"publish_date":{{post.date|jsonify}},
11+
"excerpt": {{ post.excerpt | strip_html | strip_newlines | jsonify }},
12+
"tags": {{ post.tags | jsonify }},
13+
"categories":{{post.categories | jsonify}}
14+
}{% unless forloop.last %},{% endunless %}
15+
{% endfor %}
16+
]

0 commit comments

Comments
 (0)