Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9912f0a4a7 |
@@ -1,69 +0,0 @@
|
|||||||
# Advanced compose.yaml with additional options
|
|
||||||
# Rename to compose.yaml to use this configuration
|
|
||||||
|
|
||||||
services:
|
|
||||||
portfolio:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
container_name: portfolio
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
# Environment variables
|
|
||||||
environment:
|
|
||||||
- NODE_ENV=production
|
|
||||||
# Add any custom Next.js environment variables here
|
|
||||||
# - NEXT_PUBLIC_SITE_URL=https://portfolio.yourdomain.com
|
|
||||||
|
|
||||||
# Health check
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 40s
|
|
||||||
|
|
||||||
networks:
|
|
||||||
- traefik
|
|
||||||
|
|
||||||
labels:
|
|
||||||
# Enable Traefik
|
|
||||||
- "traefik.enable=true"
|
|
||||||
|
|
||||||
# HTTP Router
|
|
||||||
- "traefik.http.routers.portfolio.rule=Host(`portfolio.yourdomain.com`)"
|
|
||||||
- "traefik.http.routers.portfolio.entrypoints=web"
|
|
||||||
|
|
||||||
# HTTPS Router
|
|
||||||
- "traefik.http.routers.portfolio-secure.rule=Host(`portfolio.yourdomain.com`)"
|
|
||||||
- "traefik.http.routers.portfolio-secure.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.portfolio-secure.tls=true"
|
|
||||||
- "traefik.http.routers.portfolio-secure.tls.certresolver=letsencrypt"
|
|
||||||
|
|
||||||
# HTTP to HTTPS Redirect
|
|
||||||
- "traefik.http.routers.portfolio.middlewares=portfolio-redirect"
|
|
||||||
- "traefik.http.middlewares.portfolio-redirect.redirectscheme.scheme=https"
|
|
||||||
- "traefik.http.middlewares.portfolio-redirect.redirectscheme.permanent=true"
|
|
||||||
|
|
||||||
# Optional: Security Headers
|
|
||||||
- "traefik.http.routers.portfolio-secure.middlewares=portfolio-headers"
|
|
||||||
- "traefik.http.middlewares.portfolio-headers.headers.customFrameOptionsValue=SAMEORIGIN"
|
|
||||||
- "traefik.http.middlewares.portfolio-headers.headers.customResponseHeaders.X-Robots-Tag=index,follow"
|
|
||||||
- "traefik.http.middlewares.portfolio-headers.headers.sslRedirect=true"
|
|
||||||
- "traefik.http.middlewares.portfolio-headers.headers.stsSeconds=31536000"
|
|
||||||
- "traefik.http.middlewares.portfolio-headers.headers.stsIncludeSubdomains=true"
|
|
||||||
- "traefik.http.middlewares.portfolio-headers.headers.stsPreload=true"
|
|
||||||
|
|
||||||
# Service
|
|
||||||
- "traefik.http.services.portfolio.loadbalancer.server.port=3000"
|
|
||||||
|
|
||||||
# Dockge metadata
|
|
||||||
- "com.dockge.project=portfolio"
|
|
||||||
- "com.dockge.description=Personal portfolio website"
|
|
||||||
|
|
||||||
# Watchtower auto-update (optional, if you use Watchtower)
|
|
||||||
- "com.centurylinklabs.watchtower.enable=true"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
traefik:
|
|
||||||
external: true
|
|
||||||
+4
-19
@@ -6,33 +6,18 @@ services:
|
|||||||
container_name: portfolio
|
container_name: portfolio
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- traefik
|
- proxy
|
||||||
labels:
|
labels:
|
||||||
# Enable Traefik
|
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.portfolio-secure.rule=Host(`site.musyzn.dev`)"
|
||||||
# HTTP Router
|
|
||||||
- "traefik.http.routers.portfolio.rule=Host(`portfolio.yourdomain.com`)"
|
|
||||||
- "traefik.http.routers.portfolio.entrypoints=web"
|
|
||||||
|
|
||||||
# HTTPS Router
|
|
||||||
- "traefik.http.routers.portfolio-secure.rule=Host(`portfolio.yourdomain.com`)"
|
|
||||||
- "traefik.http.routers.portfolio-secure.entrypoints=websecure"
|
- "traefik.http.routers.portfolio-secure.entrypoints=websecure"
|
||||||
- "traefik.http.routers.portfolio-secure.tls=true"
|
- "traefik.http.routers.portfolio-secure.tls=true"
|
||||||
- "traefik.http.routers.portfolio-secure.tls.certresolver=letsencrypt"
|
- "traefik.http.routers.portfolio-secure.tls.certresolver=letsencrypt"
|
||||||
|
|
||||||
# HTTP to HTTPS Redirect
|
|
||||||
- "traefik.http.routers.portfolio.middlewares=portfolio-redirect"
|
|
||||||
- "traefik.http.middlewares.portfolio-redirect.redirectscheme.scheme=https"
|
|
||||||
- "traefik.http.middlewares.portfolio-redirect.redirectscheme.permanent=true"
|
|
||||||
|
|
||||||
# Service
|
|
||||||
- "traefik.http.services.portfolio.loadbalancer.server.port=3000"
|
- "traefik.http.services.portfolio.loadbalancer.server.port=3000"
|
||||||
|
|
||||||
# Dockge metadata (optional, for better organization in Dockge)
|
- "com.dockge.project=site"
|
||||||
- "com.dockge.project=portfolio"
|
|
||||||
- "com.dockge.description=Personal portfolio website"
|
- "com.dockge.description=Personal portfolio website"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
traefik:
|
proxy:
|
||||||
external: true
|
external: true
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
---
|
||||||
|
title: 'Bluetooth on Linux'
|
||||||
|
date: '2025-12-08'
|
||||||
|
excerpt: 'Learn how to use bluetooth on a debian based linux distribution.'
|
||||||
|
---
|
||||||
|
|
||||||
|
So I've been on quite the journey learning linux as my daily driver operating system.
|
||||||
|
Today I wanted to pair my bluetooth keyboard to my desktop because.. why not, I like swapping between a few keyboards sometimes.
|
||||||
|
I went to the panel/app bar and saw no trace of a 'bluetooth' icon I had come to expect during my days on Windows and MacOS.
|
||||||
|
I attempted to look for a 'bluetooth' app to no avail and then finally went to the internet.
|
||||||
|
|
||||||
|
It didn't take long to find that my flavor of linux (mint) has a built in `bluetoothctl` tool that we can use.
|
||||||
|
|
||||||
|
## bluetoothctl
|
||||||
|
|
||||||
|
There are two ways to use `bluetoothctl` the first is by prepending every command with `bluetoothctl`. This is how the tutorial ran me through it but I wasn't a big fan and opted for the alternative way.
|
||||||
|
|
||||||
|
If you just type `bluetoothctl` you will enter an interactive utility.
|
||||||
|
|
||||||
|
```
|
||||||
|
muszyn:~/$ bluetoothctl
|
||||||
|
[Keychron K6 Pro]# Agent registered
|
||||||
|
[Keychron K6 Pro]# [CHG] Controller B4:6B:FC:6A:DB:27 Pairable: yes
|
||||||
|
```
|
||||||
|
|
||||||
|
> You may notice that I have a bluetooth device already registered `Keychron K6 Pro`, this is the keyboard I am currently using.
|
||||||
|
|
||||||
|
Once you are in the control menu there are a list of commands to easily get started:
|
||||||
|
|
||||||
|
> you can type `help` at any time to print a list of all available commands.
|
||||||
|
|
||||||
|
- scan on | scan off
|
||||||
|
- pair `{device-mac-addr}`
|
||||||
|
- connect `{device-mac-addr}`
|
||||||
|
- devices
|
||||||
|
- remove `{device-mac-addr}`
|
||||||
|
- disconnect `{device-mac-addr}`
|
||||||
|
|
||||||
|
So lets put these commands to work.
|
||||||
|
|
||||||
|
## Scanning for Devices
|
||||||
|
|
||||||
|
To search for a bluetooth device that you can connect to use the scan command.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
scan on
|
||||||
|
```
|
||||||
|
|
||||||
|
This will begin discovery and output the devices that your system detects.
|
||||||
|
|
||||||
|
```
|
||||||
|
[Keychron K6 Pro]# scan on
|
||||||
|
[Keychron K6 Pro]# SetDiscoveryFilter success
|
||||||
|
[Keychron K6 Pro]# Discovery started
|
||||||
|
[Keychron K6 Pro]# [CHG] Controller B4:6B:FC:6A:DB:27 Discovering: yes
|
||||||
|
[Keychron K6 Pro]# [NEW] Device 55:41:D0:21:FD:EE 55-41-D0-21-FD-EE
|
||||||
|
[Keychron K6 Pro]# [NEW] Device 04:D5:83:26:88:0A KM18
|
||||||
|
```
|
||||||
|
|
||||||
|
The output above has a good deal of information so lets break it down.
|
||||||
|
|
||||||
|
Bluetooth devices are labeled as **Device** follwed by their Media Access Control (MAC) addresses which is a unique identifier for the device. All MAC addresses follow the format **XX:XX:XX:XX:XX:XX**. If the device has a name associated with it like *KM18*, bluetoothctl will display it. However, not every device has a display name as shown above by *55-41-D0-21-FD-EE* which is just the MAC address with '-' instead of ':'.
|
||||||
|
|
||||||
|
## Connecting to a Device
|
||||||
|
|
||||||
|
Once we have found a list of available devices we can choose to connect to one.
|
||||||
|
|
||||||
|
The first step is to pair your system to the device using the `pair` command.
|
||||||
|
Using KM18 in the list above:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pair 04:D5:83:26:88:0A
|
||||||
|
```
|
||||||
|
|
||||||
|
> Note: when using the interactive utility you can press `TAB` twice to ouput the available MAC addresses, begin typing one and then press `TAB` once to auto-fill the rest of the address.
|
||||||
|
|
||||||
|
If this isn't your first time pairing to the device then you can use the `connect` command to establish a bluetooth connection.
|
||||||
|
This is useful if your device does not automatically connect on startup or if you would like to take over the connection from another device (this happens all the time with my headphones).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
connect 04:D5:83:26:88:0A
|
||||||
|
```
|
||||||
|
|
||||||
|
## Listing Paired Devices
|
||||||
|
|
||||||
|
Using the utility listing paried devices can be useful if you don't want to `scan` all the time.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
devices Paried
|
||||||
|
```
|
||||||
|
|
||||||
|
This will output a list of your paired devices that you can then use to connect/disconnect from your system.
|
||||||
|
|
||||||
|
## Disconnecting Devices
|
||||||
|
|
||||||
|
To unpair the device use the `remove` command.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
remove 04:D5:83:26:88:0A
|
||||||
|
```
|
||||||
|
|
||||||
|
To disconnect the device use the `disconnect` command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
disconnect 04:D5:83:26:88:0A
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exiting the Interactive Mode
|
||||||
|
|
||||||
|
To exit, either type `exit`, or `quit`, OR you can use `ctl+D` whichever you prefer.
|
||||||
|
|
||||||
|
## Non-Interactive
|
||||||
|
|
||||||
|
If you want to use the non-interactive tool then simply place `bluetoothctl` in front of each command.
|
||||||
|
The primary benefit I found for the interactive tool was the tab completion for the MAC addresses :D.
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Building Beautiful UIs with shadcn/ui'
|
|
||||||
date: '2025-12-08'
|
|
||||||
excerpt: 'Discover how shadcn/ui can accelerate your UI development with beautiful, accessible components.'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Building Beautiful UIs with shadcn/ui
|
|
||||||
|
|
||||||
shadcn/ui has revolutionized how we build component libraries. Unlike traditional component libraries, shadcn/ui gives you full ownership of your components.
|
|
||||||
|
|
||||||
## What Makes shadcn/ui Different?
|
|
||||||
|
|
||||||
Instead of installing components as dependencies, shadcn/ui copies the component code directly into your project. This means:
|
|
||||||
|
|
||||||
- **Full Control**: Modify components however you need
|
|
||||||
- **No Lock-in**: You own the code, no vendor lock-in
|
|
||||||
- **Tailwind CSS**: Built on top of Tailwind CSS for easy customization
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
Installation is straightforward:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx shadcn@latest init
|
|
||||||
```
|
|
||||||
|
|
||||||
Then add components as needed:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npx shadcn@latest add button
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
Since the components are in your codebase, customization is as simple as editing the files. No need to override styles or fight with CSS specificity.
|
|
||||||
|
|
||||||
shadcn/ui is the perfect choice for teams that want beautiful components with complete control.
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Getting Started with Next.js'
|
|
||||||
date: '2025-12-12'
|
|
||||||
excerpt: 'An introduction to building modern web applications with Next.js and React.'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Getting Started with Next.js
|
|
||||||
|
|
||||||
Next.js has become one of the most popular frameworks for building React applications. In this post, we'll explore why Next.js is such a powerful choice for modern web development.
|
|
||||||
|
|
||||||
## What is Next.js?
|
|
||||||
|
|
||||||
Next.js is a React framework that enables functionality such as server-side rendering and generating static websites. It's built by Vercel and has become the go-to choice for many developers.
|
|
||||||
|
|
||||||
## Key Features
|
|
||||||
|
|
||||||
- **Server-Side Rendering**: Render your React components on the server for better performance and SEO.
|
|
||||||
- **Static Site Generation**: Pre-render pages at build time for lightning-fast load times.
|
|
||||||
- **File-based Routing**: Create routes by simply adding files to the `app` directory.
|
|
||||||
- **API Routes**: Build API endpoints right within your Next.js application.
|
|
||||||
|
|
||||||
## Why Choose Next.js?
|
|
||||||
|
|
||||||
Next.js takes care of many of the common challenges in web development, allowing you to focus on building features rather than configuration.
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Tailwind CSS Tips and Tricks'
|
|
||||||
date: '2025-12-05'
|
|
||||||
excerpt: 'Level up your Tailwind CSS skills with these advanced tips and tricks.'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Tailwind CSS Tips and Tricks
|
|
||||||
|
|
||||||
Tailwind CSS has changed how we write styles. Here are some advanced tips to take your Tailwind skills to the next level.
|
|
||||||
|
|
||||||
## Use @apply Sparingly
|
|
||||||
|
|
||||||
While `@apply` is useful for extracting repeated patterns, overusing it defeats the purpose of utility-first CSS. Keep most styles in your JSX.
|
|
||||||
|
|
||||||
## Leverage JIT Mode
|
|
||||||
|
|
||||||
The Just-In-Time compiler generates styles on-demand, giving you:
|
|
||||||
|
|
||||||
- Faster build times
|
|
||||||
- Smaller file sizes
|
|
||||||
- All variants enabled by default
|
|
||||||
|
|
||||||
## Custom Utilities
|
|
||||||
|
|
||||||
Extend Tailwind with custom utilities in your `tailwind.config.js`:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
module.exports = {
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
spacing: {
|
|
||||||
'128': '32rem',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
These tips will help you use Tailwind CSS more effectively and build better UIs faster.
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'TypeScript Best Practices for 2025'
|
|
||||||
date: '2025-12-10'
|
|
||||||
excerpt: 'Learn the latest TypeScript best practices to write more maintainable and type-safe code.'
|
|
||||||
---
|
|
||||||
|
|
||||||
# TypeScript Best Practices for 2025
|
|
||||||
|
|
||||||
TypeScript has evolved significantly, and with it, the best practices for writing type-safe code have also matured. Let's explore some essential practices for 2025.
|
|
||||||
|
|
||||||
## Use Strict Mode
|
|
||||||
|
|
||||||
Always enable strict mode in your `tsconfig.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"strict": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Leverage Type Inference
|
|
||||||
|
|
||||||
TypeScript's type inference is powerful. Let the compiler infer types when it's obvious:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Good
|
|
||||||
const count = 42;
|
|
||||||
|
|
||||||
// Unnecessary
|
|
||||||
const count: number = 42;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Avoid `any`
|
|
||||||
|
|
||||||
The `any` type defeats the purpose of TypeScript. Use `unknown` instead when the type is truly unknown, or take time to properly type your data.
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
Following these best practices will help you write more maintainable and bug-free TypeScript code.
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
title: 'Homelab Server'
|
||||||
|
description: 'A personal server that replicates a plethora of self-hosted solutions'
|
||||||
|
links:
|
||||||
|
github: 'https://github.com/amuszyn/homelab'
|
||||||
|
---
|
||||||
|
|
||||||
|
# Homelab Server
|
||||||
|
|
||||||
|
A personal server that replicates a plethora of self-hosted solutions.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Git server
|
||||||
|
- Reverse proxy
|
||||||
|
- Log aggregation and filtering
|
||||||
|
- Monitoring and visualization
|
||||||
|
- Network wide ad-blocking
|
||||||
|
- VPN
|
||||||
|
- Automatic photo backup
|
||||||
|
- Network Security
|
||||||
|
|
||||||
|
## Built With
|
||||||
|
|
||||||
|
- Dockge
|
||||||
|
- Docker
|
||||||
|
- Graphana
|
||||||
|
- Prometheus
|
||||||
|
- Traefik
|
||||||
|
- Gitea
|
||||||
|
- Wireguard
|
||||||
|
- PiHole
|
||||||
|
- Cloudflare
|
||||||
|
- Immich
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Markdown Editor'
|
|
||||||
description: 'A sleek markdown editor with live preview and export options'
|
|
||||||
links:
|
|
||||||
github: 'https://github.com/username/markdown-editor'
|
|
||||||
gitea: 'https://gitea.example.com/username/markdown-editor'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Markdown Editor
|
|
||||||
|
|
||||||
A beautiful and intuitive markdown editor with real-time preview, syntax highlighting, and multiple export formats.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Live preview
|
|
||||||
- Syntax highlighting
|
|
||||||
- Export to PDF, HTML
|
|
||||||
- Dark mode support
|
|
||||||
- Keyboard shortcuts
|
|
||||||
- Auto-save
|
|
||||||
|
|
||||||
## Built With
|
|
||||||
|
|
||||||
- React
|
|
||||||
- CodeMirror
|
|
||||||
- react-markdown
|
|
||||||
- Tailwind CSS
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
---
|
|
||||||
title: 'Task Manager App'
|
|
||||||
description: 'A collaborative task management application with real-time updates'
|
|
||||||
links:
|
|
||||||
github: 'https://github.com/username/task-manager'
|
|
||||||
live: 'https://tasks.example.com'
|
|
||||||
---
|
|
||||||
|
|
||||||
# Task Manager App
|
|
||||||
|
|
||||||
A full-stack task management application that helps teams collaborate and stay organized.
|
|
||||||
|
|
||||||
## Key Features
|
|
||||||
|
|
||||||
- Real-time collaboration
|
|
||||||
- Task assignments and due dates
|
|
||||||
- Project organization
|
|
||||||
- Priority levels
|
|
||||||
- Search and filtering
|
|
||||||
|
|
||||||
## Tech Stack
|
|
||||||
|
|
||||||
- Frontend: React, TypeScript
|
|
||||||
- Backend: Node.js, Express
|
|
||||||
- Database: PostgreSQL
|
|
||||||
- Real-time: Socket.io
|
|
||||||
Reference in New Issue
Block a user