diff --git a/config/_default/permalinks.yaml b/config/_default/permalinks.yaml index 8efe757..7d4b0bc 100644 --- a/config/_default/permalinks.yaml +++ b/config/_default/permalinks.yaml @@ -1,2 +1,3 @@ blog: blog/:year/:month/:slug/ photos: photos/:year/:month/:slug/ +twitter: twitter/:year/:month/:slug/ diff --git a/content/_index.es.md b/content/_index.es.md index 4812de4..dec3a59 100644 --- a/content/_index.es.md +++ b/content/_index.es.md @@ -1,8 +1,20 @@ --- -title: Eryn Rachel Wells layout: single +draft: true +params: + renderHeadingAnchors: false --- -{{< nobreak >}}Ingeniera de software,{{< /nobreak >}} -alfarera, música, y -{{< nobreak >}}nerd en general.{{< /nobreak >}} +¡Hola! Me llamo Eryn Wells. Este es mi sitio web. ¡Bienvenidos! + + +## Personal + +Soy mujer queer, + + +## Profesional + +Desde 2011, he trabajado como ingeniera de software en varios companías alrededor del área +del Bahía de San Francisco. En 2016, me uní a [Apple][]. Hoy, trabajo en +tecnologías que diff --git a/content/_index.md b/content/_index.md index 320c794..e4ca8ce 100644 --- a/content/_index.md +++ b/content/_index.md @@ -6,53 +6,61 @@ params: Hi, I'm Eryn Wells. This is my website. Welcome! + ## Latest Here are some of my most recent posts. {{< home/latest >}} + ## Personal -I'm a queer trans woman, {{< tess >}}' partner, and mom of [two cats][cats]. I +I'm a queer woman, {{< tess >}}' partner, and mom of [two cats][cats]. I was born in Seattle, {{< abbr Washington >}}WA{{< /abbr >}} and grew up in -Phoenix, {{< abbr Arizona >}}AZ{{< /abbr >}}. I attended [Oberlin College][ob] +Phoenix, {{< abbr Arizona >}}AZ{{< /abbr >}}. I attended [Oberlin College][] where I got a degree in Computer Science. My pronouns are [she/her][pronouns]. You can read more about me on my [about][ab] page, or [get in touch][where-am-i]. + ## Professional I've worked as a software engineer since 2011 for a variety of companies around -the San Francisco Bay Area. I joined [Apple][a] in 2016, where I currently work +the San Francisco Bay Area. I joined [Apple][] in 2016, where I currently work on password management and authentication technologies. My [résumé][r] has all the details. + ## Hobbies When I'm not working, you can reliably find me hacking on this website or [some -coding other project][gh]. I'm also a musician, and play piano, Irish tin -whistle, and modular synthesizer. Occasionally I [record][bc] [things][sc]. I -love outer space and astronomy; I will always get excited to look at the moon -with you, or check out anything through a telescope. I enjoy [photograhy][p], -mostly as a travel hobby. And I've been practicing iaido, a traditional Japanese -sword art, since early 2024. Other things I've been into include: bread baking, +other coding project][src]. I'm also a musician: I play piano, Irish tin +whistle, and modular synthesizer. Occasionally I [record things][sc] or offer +them [for sale][sc]. I love outer space and astronomy; I will always get excited +to look at the moon with you, or check out anything through a telescope. I enjoy +[photograhy][p], mostly as a travel hobby. And I've been practicing +[iaidō][mjer], a traditional Japanese sword art, at [Nishi Kaigan Iaidō +Dōjō][nkid] since early 2024. Other things I've been into include: bread baking, bicycling, calligraphy, ceramics, and knitting. -[a]: https://apple.com + +[Apple]: https://apple.com [ab]: {{< ref "/about" >}} [b]: {{< ref "/blog" >}} [bc]: https://erynwells.bandcamp.com/releases [cats]: {{< ref "/cats" >}} [eml]: mailto:Eryn%20Wells -[gh]: https://github.com/erynofwales +[src]: https://source.erynwells.me/eryn [ig]: https://www.instagram.com/erynofwales [m]: https://mastodon.social/@erynofwales [n]: {{< ref "/now" >}} -[ob]: https://www.oberlin.edu +[Oberlin College]: https://www.oberlin.edu [p]: {{< ref "/photos" >}} [pronouns]: http://pronoun.is/she [r]: {{< ref "/resume" >}} [sc]: https://soundcloud.com/purlsnbeeps [where-am-i]: {{< ref "/about/where-am-i" >}} +[mjer]: https://en.wikipedia.org/wiki/Mus%C5%8D_Jikiden_Eishin-ry%C5%AB +[nkid]: https://iaido.org diff --git a/content/blog/2026/thirty-eight/index.md b/content/blog/2026/thirty-eight/index.md new file mode 100644 index 0000000..6a44e0b --- /dev/null +++ b/content/blog/2026/thirty-eight/index.md @@ -0,0 +1,14 @@ +--- +title: "Thirty Eight" +date: 2026-01-14 +draft: true +tags: + - Me + - Birthdays +--- + +I'm turning thirty eight today! + +Neil Armstrong was 38 when he walked on the moon. (Buzz Aldrin was 39.) Jack +Swigert was 38 when he timed the 14 second burn that brought Apollo 13 back into +position for reentry to Earth. diff --git a/content/photos/2025/harvest-moon/harvest-moon.png b/content/photos/2025/harvest-moon/harvest-moon.png new file mode 100644 index 0000000..8a80b4c Binary files /dev/null and b/content/photos/2025/harvest-moon/harvest-moon.png differ diff --git a/content/photos/2025/harvest-moon/index.md b/content/photos/2025/harvest-moon/index.md new file mode 100644 index 0000000..e81ead0 --- /dev/null +++ b/content/photos/2025/harvest-moon/index.md @@ -0,0 +1,23 @@ +--- +title: "Harvest Moon" +date: 2025-10-06T22:00:00-07:00 +tags: + - Space + - Astrophotography + - Moon +--- + +Monday October 6 was the full moon. As the closest full moon to the [autumnal +equinox][], it is the [Harvest Moon][]. It also happened to be a [supermoon][], +making it slightly bigger in the night sky. + +I shot this photo from my back deck with my Fujifilm X-T5 and a Canon 100mm +macro prime[^1]. Amazingly, this is a handheld shot too. I couldn't find a +necessary bit of my tripod to mount the camera, so I made do. + +[^1]: Photography nerds will notice these are _not_ compatible components; I use + a Fringer EF-FX mount adapter for this. + +[autumnal equinox]: https://en.wikipedia.org/wiki/September_equinox +[Harvest Moon]: https://en.wikipedia.org/wiki/Full_moon#Harvest_moon +[supermoon]: https://science.nasa.gov/moon/supermoons/ diff --git a/content/tags/eaoc/_index.md b/content/tags/eaoc/_index.md new file mode 100644 index 0000000..d5330a3 --- /dev/null +++ b/content/tags/eaoc/_index.md @@ -0,0 +1,5 @@ +--- +title: Erin Anne O'Connor +linkTitle: EAOC +slug: eaoc +--- diff --git a/content/uses/index.tok.md b/content/uses/index.tok.md new file mode 100644 index 0000000..7a04568 --- /dev/null +++ b/content/uses/index.tok.md @@ -0,0 +1,138 @@ +--- +title: "mi kepeken e ni" +draft: true +toc: open +--- + +## Tech + +### Hardware + +[Apple M2 MacBook Air from 2022](https://www.apple.com/macbook-air-13-and-15-m2/) +: mi olin e ilo sona ni. tenpo pini la mi olin e ilo sona ante. ilo sona ante en +ilo sona ni li MacBook Air. tenpo ale la mi jo e ilo sona ante. kin la tenpo ale +la mi jo e ilo sona ni. + +[Apple Studio Display](https://www.apple.com/studio-display/) +: I was on the fence about a Cinema Display for a long time. I ordered and +canceled three times. Ultimately I gave in, and I'm quite happy with it. It's +mounted on a VESA arm attached to my desktop. + +### Software + +#### Development + +[Neovim](https://neovim.io/) +: tenpo suli la, mi kepeken e `vim`. ona li ilo nanpa wan pi pali lipu mi. + +[Visual Studio Code](https://code.visualstudio.com/) +: tenpo sike mute la mi alasa e VSCode. ona li jo e ijo pona mute. + +[Xcode](https://developer.apple.com/xcode/) +: mi pali lon [kulupu kili][apple]. Xcode li ilo pi pali lipu tawa. lon kulupu +kili la mi kepeken e Xcode. lon tomo mi, mi kepeken kin e Xcode. Xcode li pona. + +[Fork](https://fork.dev) +: A GUI client for `git`. I think Fork has totally changed how I use `git`. I +still use the command line for many things, but working through diffs, staging +changes, and even rebasing is so much easier in a GUI. + +#### Terminal + +[Terminal.app](https://support.apple.com/guide/terminal/welcome/mac) +: macOS's built in terminal emulator is solid. The only thing I miss from it now +and then is "true color" support, and that's only when I try to install a new +color theme in Neovim and everything goes haywire. + +[Zsh](https://www.zsh.org) +: I've been using Zsh since before it was cool. My shell config is full of +bespoke tweaks, including a prompt theme I'm rather proud of. + +#### Hosting + +[Digital Ocean](https://www.digitalocean.com) +: DO has hosted my VPS for a number of years. I moved there from Linode because +I wanted to run FreeBSD on my server. + +[FreeBSD](https://www.freebsd.org) +: My server OS of choice. It's secure, simple, and resilient, and I appreciate +the less-encumbered BSD license. + +[FastMail](https://www.fastmail.com/) +: I've used FastMail for years now as my email host. Their annual fees are quite +modest and they have a great feature set including a Sieve email filter editor, +and Masked Email for genearating ad hoc email addresses. I've never had a +problem with uptime, and the few times I've contacted support, they've been +helpful. + +[Hugo](https://gohugo.io) +: This whole website is built with Hugo. + +### Mobile + +[Doppler](https://brushedtype.co/doppler/) +: File-based music player. + +[Ivory](https://tapbots.com/ivory/) +: My Mastodon client of choice for macOS and iOS. + +[Overcast](https://overcast.fm/podcasts) +: My podcast player of choice. + +[Reeder](https://www.reederapp.com) +: RSS feed organizer and reader. I'm doing a lot more RSS these days. + +[Transit](https://transitapp.com) +: Helps me stay on top of bus schedules in San Francisco. + +## Music + +[Logic Pro](https://www.apple.com/logic-pro/) +: Apple's DAW is full of features and plugins (far more than I could ever use) +and it's hard to beat the corporate discount, much as I also love Ableton. + +[Shure SM7B](https://www.shure.com/en-US/products/microphones/sm7b) +: The SM7 is an iconic mic, and has been the go-to for voice actors, podcasters, +and musicians for 50 years. The excellent podcast Twenty Thousand Hertz did a +great [deep dive episode][20ksm7] on its history and place in the audio +industry. I have one on my desk at home, and it makes me sound great on work +video calls, and the occasional audio recording. + +[Moog Matriarch](https://www.moogmusic.com/synthesizers?type=202) +: I'm a bit of a Moog fangirl, and this might be my favorite of their synths. +It's just hard to beat the sound of a Moog. + +[Kawaii CA-65](https://kawaius.com/product/ca65/) +: I've been playing piano since I was seven years old. A digital piano is +perfect for the small apartments I've called home. This one has a fantastic +realistic action and it sounds great. + +## Coffee + +[Baratza Encore](https://www.baratza.com/product/encoretm-zcg485) +: It's affordable and does a pretty good job. + +[Kalita Wave](https://kalitausa.com/products/kalita-wave-185-stainless-steel-coffee-dripper) +: The Kalita is probably the easist single serve pour over dripper I've used. + +[Chemex](https://www.chemexcoffeemaker.com/six-cup-classic-series-coffeemaker.html) +: If I'm making coffee for more than just me, the Chemex is the biggest pour +over vessel I have. Makes yummy coffee too. + +## Gaming + +[Nintendo Switch](https://www.nintendo.com/us/switch/) +: Most of my gaming happens here. I play a lot of Mario Kart online with +friends, and I'm a big fan of both of the major Legend of Zelda titles that have +come out for it: Breath of the Wild and Tears of the Kingdom. + +[PlayStation 5](https://www.playstation.com/en-us/ps5/) +: I also have a PS5. I've played a ton of Horizon: Zero Dawn and the new Final +Fantasy 7 games. + +[Analogue Pocket](https://www.analogue.co/pocket) +: When I want to play my stock of Game Boy games, this thing is great. + +[apple]: https://www.apple.com +[vscode-vim]: https://marketplace.visualstudio.com/items?itemName=vscodevim.vim +[20ksm7]: https://www.20k.org/episodes/sm7 diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index d9e75ac..0000000 --- a/deploy.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env zsh -# Deploy erynwells.me to my web root -# Eryn Wells - -print -P "%BFiltering .DS_Store files%b" -find . -name '.DS_Store' -print -delete - -print -P "%BGenerating site%b" -hugo - -echo -print -P "%BRsyncing site to nutmeg.erynwells.me%b" -rsync -avz --no-times --no-perms --delete public/ \ - eryn@nutmeg.erynwells.me:/srv/www/erynwells.me/html diff --git a/layouts/shortcodes/abbr.html b/layouts/shortcodes/abbr.html index aa4e645..831c7f8 100644 --- a/layouts/shortcodes/abbr.html +++ b/layouts/shortcodes/abbr.html @@ -1 +1 @@ -{{ .Inner }} +{{ .Inner }}{{- "" -}} diff --git a/scripts/erynwells_me/paths.py b/scripts/erynwells_me/paths.py index e20abc2..5b7f51b 100644 --- a/scripts/erynwells_me/paths.py +++ b/scripts/erynwells_me/paths.py @@ -4,16 +4,33 @@ import os.path as osp +def root_dir() -> str: + '''Return the path to the root of the repository.''' + return osp.normpath(osp.join(osp.dirname(__file__), '..', '..')) + + +def assets_path() -> str: + '''Return the path to the assets directory.''' + path = osp.join(root_dir(), 'assets') + return path + + def content_path() -> str: '''Return the path to the content directory.''' - path = osp.abspath(osp.join(osp.dirname(__file__), '..', '..', 'content')) - assert osp.isdir(path) + path = osp.join(root_dir(), 'content') return path def blog_path() -> str: + '''Return the path to the blog content directory.''' return osp.join(content_path(), 'blog') def photos_path() -> str: + '''Return the path to the photos content directory.''' return osp.join(content_path(), 'photos') + + +content_dir = content_path +blog_dir = blog_path +photos_dir = photos_path diff --git a/scripts/erynwells_me/weeknotes.py b/scripts/erynwells_me/weeknotes.py index a014dd4..4115f2b 100644 --- a/scripts/erynwells_me/weeknotes.py +++ b/scripts/erynwells_me/weeknotes.py @@ -12,7 +12,7 @@ from .scripting import Command class WeeknotesCommand(Command): @staticmethod - def weeknotes_filename(year: str, week: str) -> str: + def weeknotes_filename(year: str | int, week: str | int) -> str: return f'weeknotes-{year}w{week}.md' @staticmethod @@ -26,7 +26,7 @@ class WeeknotesCommand(Command): week_number_str = next_sunday.strftime('%V') return blog.post_path(WeeknotesCommand.weeknotes_filename( - str(year), + year, week_number_str )) diff --git a/scripts/new-photo-post b/scripts/new-photo-post index b36ba18..bb04719 100755 --- a/scripts/new-photo-post +++ b/scripts/new-photo-post @@ -14,12 +14,23 @@ from erynwells_me.metadata import slugify from erynwells_me.paths import photos_path +def date_argument(value: str) -> datetime.datetime: + parsed_date = datetime.datetime.fromisoformat(value) + + if not parsed_date.tzinfo: + local_timezone = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo + parsed_date = datetime.datetime.combine(parsed_date.date(), parsed_date.time(), local_timezone) + + return parsed_date + + def parse_args(argv, *a, **kw): parser = argparse.ArgumentParser(*a, **kw) parser.add_argument('-e', '--edit', action='store_true') parser.add_argument('-n', '--dry-run', action='store_true') parser.add_argument('-t', '--title') parser.add_argument('-s', '--slug') + parser.add_argument('-d', '--date', type=date_argument) parser.add_argument('--dump-exif', action='store_true') parser.add_argument('photos', nargs='+') args = parser.parse_args(argv) @@ -29,7 +40,7 @@ def parse_args(argv, *a, **kw): def main(argv): args = parse_args(argv[1:], prog=argv[0]) - earliest_exif_date: Optional[datetime.datetime] = None + post_date: Optional[datetime.datetime] = args.date for index, photo in enumerate(args.photos): print(f'image\t\t{photo}') @@ -40,14 +51,20 @@ def main(argv): continue raw_exif = image._getexif() - friendly_exif = {TAGS[k]: v for k, v in raw_exif.items() if k in TAGS} + friendly_exif = {} + if raw_exif: + friendly_exif = {TAGS[k]: v for k, v in raw_exif.items() if k in TAGS} - try: - date_string = f'{friendly_exif["DateTime"]} {friendly_exif["OffsetTime"]}' - exif_date = datetime.datetime.strptime(date_string, '%Y:%m:%d %H:%M:%S %z') - except KeyError: - exif_date = datetime.datetime.strptime(friendly_exif["DateTime"], '%Y:%m:%d %H:%M:%S') - print(f'capture-time\t{exif_date.isoformat()}') + photo_date = None + if not args.date: + try: + date_string = f'{friendly_exif["DateTime"]} {friendly_exif["OffsetTime"]}' + photo_date = datetime.datetime.strptime(date_string, '%Y:%m:%d %H:%M:%S %z') + except KeyError: + photo_date = datetime.datetime.strptime(friendly_exif["DateTime"], '%Y:%m:%d %H:%M:%S') + else: + photo_date = args.date + print(f'capture-time\t{photo_date.isoformat()}') iso_rating = friendly_exif.get('ISOSpeedRatings') if iso_rating: @@ -66,23 +83,24 @@ def main(argv): if exposure_time: print(f'exposure-time\t{exposure_time}') - if not earliest_exif_date or exif_date < earliest_exif_date: - earliest_exif_date = exif_date + if not post_date or photo_date < post_date: + post_date = photo_date if index < len(args.photos) - 1: print() - if not earliest_exif_date: - earliest_exif_date = datetime.datetime.now() + if not post_date: + post_date = datetime.datetime.now() - year = earliest_exif_date.year - month = earliest_exif_date.month + year = post_date.year + month = post_date.month if args.slug: name = args.slug elif args.title: name = slugify(args.title) else: + photo = args.photos[0] name = osp.splitext(osp.basename(photo))[0] post_path_year = os.path.join(photos_path(), f'{year:04}', name) @@ -100,7 +118,7 @@ def main(argv): post_path = post_path_year try: - hugo_command = ['hugo', 'new', '--clock', earliest_exif_date.isoformat(), post_path] + hugo_command = ['hugo', 'new', '--clock', post_date.isoformat(), post_path] if not args.dry_run: result = subprocess.run(hugo_command) result.check_returncode() diff --git a/scripts/website b/scripts/website index 356a985..e80b933 100755 --- a/scripts/website +++ b/scripts/website @@ -6,6 +6,8 @@ A Python interface to my personal website, Erynwells.me. ''' import argparse +import os +import os.path as osp from typing import List from erynwells_me.scripting import Command from erynwells_me.weeknotes import WeeknotesCommand @@ -31,7 +33,14 @@ def parse_args(commands: List[Command], argv, *a, **kw): def main(argv): - args = parse_args(COMMANDS, argv[1:], prog=argv[0]) + program_name = osp.basename(argv[0]) + args = parse_args(COMMANDS, argv[1:], prog=program_name) + + scripts_dir = osp.dirname(__file__) + repo_root_dir = osp.normpath(osp.join(scripts_dir, '..')) + if os.getcwd() != repo_root_dir: + os.chdir(repo_root_dir) + return args.handler(args)