Skip to content

One year as an ex-academic

03-May-12

I realized the other day that it’s been just over a year since I quit graduate school, and by extension gave up on a life in academics. It was around the middle of April 2011 when I submitted my resignation letter. (I was spending the month teaching a course at my alma mater, and I felt more than a twinge of poignancy at the fact that I wrote the letter just a few hundred feet away from where I’d written my acceptance letter about nine years earlier, during my last semester of college.) Anyway, I thought I’d take a moment to reflect on how the year – my first spent as a non-student since I was four years old! – has gone.

The most personal of my fears about leaving graduate school had to do with the way I define myself. I was proud to think of myself as the academic type, and doubly proud to think of myself as a philosopher. (Observation: when someone who wears many hats does some work in philosophy, it’s common to see “philosopher” move to the front of their list of self-descriptors. Quelle prestige!) I’d spent about a third of my life under a certain avatar (in name if not always in practice), and I was nervous about casting it aside. How would I think of myself? How would I describe myself to others?

It turned out that the transition of self-definition was much less difficult than I’d feared. There are a few reasons why. First, from a practical point of view, I wasn’t really that engaged in my academic work anyway. The second half of my graduate career was characterized by attempt after semi-subconscious attempt to distract myself from the philosophical tasks at hand. These attempts were overwhelmingly successful, with the result that even when I did devote large amounts of time to doing philosophical work – which happened in fairly infrequent but significant bursts – my heart wasn’t really in it. A second, related reason for the easy transition is that, as a result of years of productive distraction, I had a number of alternative, and more meaningful, identities on which to fall back: software/web developer, educational technologist, teacher, etc. I imagine that such a transition would be far more difficult for someone who didn’t have viable alternatives.

So, from the internal point of view, the transition from academic to ex-academic went more smoothly than I’d hoped. The external transition – how the change has affected my relationships with others, or at least how I perceive the relationships – has been a little bit harder.

The thing is that, while I’m not one of the academics anymore, I spend much of my time with them. Most of my professional work is for universities, and many of my friends and co-workers are tied to schools in one way or another. Thus, I haven’t been able to quit the academic world cold turkey: I still have to go to meetings, deal with institutional BS, navigate political obstacle courses, etc. These are the crappy parts about working in universities, and becoming an ex-academic hasn’t made them any better in my case. (Admittedly, this is because of choices I’ve made to continue working where I work. I have friends who have left to go into, eg, banking.)

In addition to the more obvious annoying bureaucratic details of working within the university, there are the negative social aftereffects of dropping out: I don’t have a PhD, and never will, which means that I’m viewed (or at least, I feel like I’m viewed) in a different way. My opinion on academic matters just doesn’t matter in the same way anymore. I suppose that’s as it should be: the more time I spend away from the day-to-day of the university, the less relevant my opinions about that day-to-day become. Thus, when doing development work with universities, I’m a developer with some helpful experience in academia, rather than a technically-inclined academic. I should note that there have never been any specific instances where I’ve been called out on this distinction, or where it’s had an obviously negative effect on a relationship, but it’s always there in the background. (On a related note, I’ll probably never have a job where I, say, lead an academic computing program – but that’s not something I really want anyway.)

Thus, while I hate to sound sourgrapesesque about it, I haven’t lost much of anything by dropping out. I’m still heavily engaged in enabling the functions of the university that I find most important: teaching and scholarship. It’s just that I do it one or two levels of abstraction higher than when I was in the classroom or the library, and maybe it’s just as well.

On a personal level, the gains of dropping out have been enormous. Not only do I no longer devote any time to working on a project that I’m not really invested in (the dissertation), but I also no longer feel the crushing weight of the unfinished dissertation in my spare time. In the past year, I’ve read more broadly than ever in my life, discovering and developing areas of interest that I would never have dared to devote time to. I’m a new dad and I work from home, which means that I’ve been able to be the kind of dad I’d always hoped I’d be, without feeling guilty about the work I “should” be doing. I’m making an amount of money that is directly connected to the quality of my work, a startling and frankly disarming contrast to the way things seem to operate in universities, especially in the work I did as an adjunct. It’s been about a year since I intentionally read anything explicitly philosophical, but recently I’ve started to feel that itch again – and when I pick up a book or article, it’ll be because of an independent interest, rather than because it’s in an Important Person’s Bibliography.

So for me, quitting graduate school has been a nearly unmitigated success. It took years to work up the courage, and to develop the alternative paths that would make quitting feasible, but once those factors were in place, it was really the best decision I could have made.

Add an “Other” checkbox (with textbox) to a BuddyPress profile field

16-Apr-12

This is a pretty common form format:

Foo

Bar

Other

(Imagine that the textbox was next to the word ‘Other’ – wpautop() or something is being a stupid craphead and inserting a line break.)

It’s not really possible with BuddyPress’s xprofile fields. Today I dove into the codebase to see how hard it would be to add such a feature natively. The answer: Too.

So I wrote a hackish plugin instead, which you can get from this gist. (Note that it’s not in a plugin wrapper. Put it in your bp-custom.php.) To use: (1) On the Admin screen for a profile field, select ‘Yes’ under “Other Field”. (Note: it only works for checkbox fields!!) (2) ??? (3) Profit.

Record user role changes across a WordPress network for troubleshooting

19-Mar-12

One of my WP/BP projects experiences a perpetual problem, where every few weeks a handful of users is demoted on one of their blogs – they go mysteriously from Editor to Subscriber, or something like that. This sort of thing is a beast to troubleshoot, because it’s not readily reproducible.

So I wrote a small utility plugin that will help site administrators keep tabs on every role-change through the entire installation. Put the plugin into mu-plugins and the run the installation script, and it’ll fire up every time a user’s `wp_x_capabilities` meta key changes, and record some helpful information about it in a custom database table (user id, logged in user id, blog id, BP group id, stuff like that).

For more on the plugin, and to download it, visit its page on Github.

Sowing the seeds

13-Mar-12

Today I devoted an unusually large amount of time doing free user support for BuddyPress and WordPress (in IRC, over email, through some Trac tickets, and on WordPress StackExchange, the latter of which I’ve been experimenting with for the first time, and I find pretty cool). I say “unusually large” because while I used to do a lot of this sort of thing, it now falls to the bottom of my list of priorities – I do paid work, and when I’m not doing that I do free software development, and when I’m not doing that I try to get the hell away from my computer. As one of the leaders of the BuddyPress project, I usually justify this balance to myself by saying: There are lots of people who can provide user support for this software as well as I can, but there are few who can do productive development for it like I can, so my time is better spent developing. Generally, I think this is a pretty good argument. But I’m glad that days like today come along occasionally, because they remind me of some basic things about the nature of the community around a piece of free software that you can forget when your head is buried too deep in the codebase.

As an aside, I should note that I use the word ‘community’ in a measured way. The word is often overapplied, as if calling a bunch of people working on similar things “the WordPress community” or “the Digital Humanities community” or “the CUNY community” will, in a feat of performative metamorphosis (like how the Queen’s saying “I dub thee Sir Boone” would ipso facto make me a knight), bring into being the thing it purports to describe. Terminological misgivings to one side, there is an undeniable sense in which the work that we do – and by “we” here I mean specifically free software developers, though the point is quite a bit more general than that – is done in a community, or at least (more formally) a network, insofar as those who work on a common piece of free software never really work in isolation from one another. The development process that underlies these software projects depends on the existence of feedback loops, from the end user to the administrator of the installation to the community leaders to the developers themselves, in the form of bug reports, software patches, feature suggestions, support requests, blog posts, and so on.

These feedback loops are not unique to free software development; they’re not even unique to software. But in free software circles the loops are perhaps uniquely malleable, and the distinctions between user and developer uniquely permeable. Each user is a potential contributor, be it through code or advocacy. But the potential is not realized automatically. It’s obvious enough that users who hate using the software and developers whose patches are ignored will never become part of the community. More interesting is the case where a newbie approaches the community with enthusiasm and skill, but where their offerings are not nurtured and so never become real contributions.

I think this happens more than we would care to admit, and I am happy to take my share of the blame. As a developer, I become emotionally attached to the project, and as a result I sometimes interpret criticism as a personal attack. The parts of development that are least exciting – hunting down and fixing the obscure bugs that affect only a small number of users but, for those users, are ruinous – these make me defensive and sometimes angry, as they take my attention away from the more generative work I’d rather be doing. I value my time so highly that I occasionally get annoyed when someone requests some of that time to answer a “simple” question. In each instance, my attitude as a developer and leader of the project could have the effect of chilling what might otherwise have been a fruitful engagement.

Taking the time to do some “support” is the ideal way to fight these tendencies. People ask questions about the software, contribute patches, suggest improvements, etc, because they like the software and want to use it. These people are friends of the project, and should not be treated as enemies. Taking the time to work directly with users is a way of closing the feedback circuit, of sowing the seeds of future collaboration and contribution. If one out of five people recommends the software to someone else, and one out of a hundred contributes back to the software in the form of documentation or code or advocacy, that’s fruitful enough to make the engagement worthwhile.

Salvaging content from a corrupted WordPress installation

13-Feb-12

Yesterday a friend emailed me asking for help. Her old WP installation had become corrupt – through a bad plugin or something – and she couldn’t bring it back to life. So she decided to start fresh, with a new WP installation on a new server. She wanted to know if it was possible to salvage her old posts, which (as she could see in PHPMyAdmin) were still in the old database. Here’s a copy of the email I wrote to her, on the off chance that it helps someone else.

Note that this technique should be used as a last resort. Generally, WP installations can be saved with a little bit of know-how and elbow grease. Also note that it assumes that you’re switching domain names in the process. Also note that I wrote this in 10 minutes, off the top of my head – amendments or corrections welcome.

===

For shorthand:
WPA is your old, corrupted installation
WPB is a brand new, totally empty installation of WP
WPC is your new production installation, on the new domain

The first step is to get your content out of WPA and into WPB. WPB should be a totally new, throwaway installation – a local installation would be ideal, but a fresh one on your webhost would be fine. (This should NOT be the same as WPC!!) Visit your WPA database (using PHPMyAdmin or whatever tool you’ve got), and export the following tables:
wp_posts
wp_postmeta
wp_comments
wp_commentmeta

In PHPMyAdmin, that usually just means checking the boxes next to those tables, and clicking an Export button somewhere in the interface.

Next, use PHPMyAdmin to view the database of WPB. Drop/delete the four tables corresponding to the ones you exported (wp_posts, wp_postmeta, wp_comments, wp_commentmeta).

Once these four tables are dropped, use PHPMyAdmin to import the versions you exported from WPA into WPB.

At this point, the posts should be safe and sound in WPB. You can verify by visiting WPB in your web browser. The next step is to use the WP export feature of WPB to get the posts out, in a format that WPC will be able to understand. Go to wp-admin on WPB > Tools > Export. Export everything to a local file. Then go to WPC Dashboard > Tools > Import (you may have to install the WP importer plugin) and import. This process should pull your old posts and pages in, without overwriting anything currently in your system.

It’s also a nice idea to set up a redirect from your old domain to your new one. (That will ensure that links to your old blog by other sites will continue to work, as well as any times you may have linked to your own old content.) Two steps:
1) At your domain registrar, make sure that your old WPA domain points to your WPC installation; this usually means putting the WPC domain as the CNAME attribute on the DNS tab.
2) FTP to WPC, and look for a file in the main WP directory called .htaccess (you may have to enable View Hidden Files or something like that). Near the top of the file, put the following lines:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^myOLDdomain\.com$ [NC]
RewriteRule ^.*$ http://myNEWdomain.com%{REQUEST_URI} [R=301,L]

Make sure to replace myOLDdomain and myNEWdomain with the relevant domain names. This will redirect any request to myolddomain.com to the corresponding URL on mynewdomain.com, meaning that all your old permalinks should continue to work.

Using init callbacks with TinyMCE and wp_editor() in WordPress

09-Feb-12

WordPress 3.3 introduced wp_editor(). It’s a big improvement over the earlier hacks needed to get a TinyMCE instance on the WP front end. But it broke the feature in my BuddyPress Docs that detected idle time. The problem, in short, was two-fold: my idle-detection JavaScript was loading before the editor was initialized, and it wasn’t detecting key presses inside of the TinyMCE iframe. The solution to both parts of the problem required passing callbacks to the TinyMCE initialization array, in the setup array. It took me a long time to figure out how to do this, so for posterity’s sake, here are some takeaways.

First, the code:

function bp_docs_add_idle_function_to_tinymce( $initArray ) {
	if ( bp_docs_is_bp_docs_page() ) {

		$initArray['setup'] = 'function(ed) {
			ed.onInit.add(
				function(ed) {
					_initJQuery();

					// Set up listeners
					jQuery(\'#\' + ed.id + \'_parent\').bind(\'mousemove\',function (evt){
						_active(evt);
					});	

					bp_docs_load_idle();

				}
			);

			ed.onKeyDown.add(
				function(ed) {
					_active();
				}
			);
		}';
	}

	return $initArray;
}
add_filter( 'tiny_mce_before_init', 'bp_docs_add_idle_function_to_tinymce' );

Some notes:

  • I’m passing a ‘setup’ parameter to the TinyMCE init array by filtering tiny_mce_before_init
  • Only do this when you’re editing a BuddyPress Doc – that’s the bp_docs_is_bp_docs_page() check. I don’t want to mess with every instance of TinyMCE on the installation.
  • The setup parameter has to be a string. This gets tricky when the string is supposed to define an unnamed JS callback, because you have to be very careful about escaping quotes. As a string, your callback has to be wrapped in quotes. Also, when WP prints the TinyMCE parameters (and when it sees that your paramater begins with the string ‘function’) it’s going to wrap it in double-quotes. After lots of messing around, I was able to get this to work by using escaped single-quotes. (If you need to double-embed quotes – like a chain of callbacks – use escaped double-quotes.)
  • Where possible, use TinyMCE’s native events. ed.onKeyDown is one of them. It allows me to call my _active() function whenever a key is pressed inside the editor.
  • There are some kinds of actions that aren’t really detectable using TinyMCE’s events. For instance, I wanted to be able to detect when someone was moving their mouse around the iframe and especially TinyMCE’s toolbar. You can see this where I’m binding my callback to mousemove in the TinyMCE _parent element.
  • _initJQuery() and bp_docs_load_idle() are my own functions that need to run after the editor has finished setting up. That’s why they, along with the bind, are called in a callback of ed.onInit – that’s the generic place to put things that need to happen once the editor is up and running.

SOPA, Media Conglomerates, and the Moral Obligation to Boycott

01-Feb-12

SOPA, in its current form, is dead. But the fight to keep the internet an open platform for communication, creativity, and commerce is far from over. Pacts like ACTA are in some ways more troubling than SOPA/PIPA, as they represent attempts of copyright extremists to do an end-run around the US Congress. (Rep. Daniel Issa has spoken about this recently.) The root problem is not a specific piece of legislation, or even a single piece of technology, but fundamental disagreements about the nature of intellectual property, the relationship between the producers and consumers of media, and the role of government regulation in shaping and enforcing worldviews (be they conservative and profit-focused, or progressive and individual-focused). The fight will continue for as long as these disagreements persist. And the copyright extremists will continue to have sway as long as they have enormous amounts of money, and as long as the political system is arranged in such a way that deep pockets dictate legislative agendas.

This conception of the problem suggests two broad strategies. First: attempt to change the political structures that allow campaign and lobbying money to play such a significant role in the legislative process. Primarily, this is an argument about campaign finance reform. For a very readable outline of the problem, as well as the sketch of a few specific strategies for combatting it, I highly recommend Lawrence Lessig’s recent book Republic, Lost. Needless to say, solving the problems of money in politics is enormously difficult and complex, so I’ll set it aside for the moment.

The strategy that I want to consider here focuses more directly on the fact that media companies are very rich, and can afford political canoodling. (Operating here on the admittedly oversimplified assumption that media companies – TV, movie, music, book publishers – are driving the legislation.) These companies get their money from the people who buy their wares. So, in theory, if everyone stopped going to the movies, buying music, watching TV, etc, then they’d have no money. In other words, a boycott.

A few days ago, I tweeted something suggestive along these lines:

When you buy music, watch TV, or see a movie, don’t forget: the makers hate the free internet & will spend huge amounts of money to kill it.

Assume that the premise here is right (namely, that the people who make media – by which I mean, those who choose which media gets created in the first place, who fund its creation, who are responsible for its distribution and marketing, etc – hate the internet as it currently stands). That means that when you make them richer by buying their stuff, you are increasing their ability to fight the internet. All things being equal, then, someone who values the open internet should not spend money in this way – that is, you’d be morally obligated to boycott.

But all things are not equal. (Such is life.) There are some factors that may mitigate the obligation to boycott:

  • How valuable is the open internet, really?

    I’m assuming that an open internet is valuable enough to defend. I may be totally wrong about this, or I may be overestimating how valuable it is. The less valuable the internet, the less obliged we are to fight against the forces that would wreck it.

  • How much collateral damage would a boycott cause?

    The supporters of SOPA/PIPA talked a lot about the zillions of Americans who make their livings working for media conglomerates. If boycotting media companies would put them all out of work and out on the street, that’d be a bad thing. Of course, this is a complete caricature. For one thing, you can (and should, and hopefully did) make the very same argument about the zillions of Internet professionals who would be harmed by stifling legislation. More importantly, it’s not as if SOPA vs non-SOPA is a zero-sum game, where media professionals all lose their jobs if SOPAesque bills don’t pass. It’s likely that piracy is not as financially harmful as these companies complain, and it’s likely that there are anti-piracy measures that would not harm Internet professionals.

    There’s another kind of collateral damage you might be worried about: the damage caused to the creative people (musicians, writers, actors) who are directly responsible for the media that people love, and the subsequent damage to the “art” itself. In addition to the general points made in the foregoing paragraph, I’ll add that this assumes that the stuff produced by these companies is worth saving. For every The Wire (or whatever your favorite piece of popular media is), there are thousands upon thousands of pieces of trash. Taking these turds out of circulation is probably a *good* thing. Moreover, new models of direct funding for quality art (think Radiohead, Louis CK, projects taking place on Kickstarter) reduce collateral damage even further.

  • How much do you value the media produced by these companies?

    If you’re a TV junkie, or you love the movies, then it’s certainly rational for you to cling to them a bit more than someone who doesn’t care about these media (see the ‘turd’ comment above).

  • How likely is it that a boycott will make a difference?

    Probably hundreds of millions of Americans are consumers of TV, movies, books, and music. For a company like NBC Universal to take notice of a boycott, much less to change corporate policies as a result of the boycott, would require huge numbers of boycotters. You might thus argue that your individual boycott would have no positive value.

    Sadly, this is at least partly true – I’m sure there are many times more people who would go to bat for their TV shows than for the kind of heady internet freedoms that intellectuals get excited about. That said, January’s blackouts demonstrated a deep dependence on the Internet for a broader swath of Americans than I might have guessed. In any case, even a single dollar kept out of media company coffers is one dollar they can’t use to fight the open internet. The “everybody else is buying media anyway” argument is the same kind of reasoning that leads to looting during blackouts. (See also Kant.)

So what does this all mean? I think that there are a couple of takeaways:

  1. I think there’s a decent case to be made for a broad boycott.
  2. Even in the absence of an organized boycott, I think there’s a decent case to be made for individuals to boycott.
  3. If you care about the internet (if you’re reading this blog post, you probably do), you cannot continue to patronize these media companies without at least recognizing the indirect effects of your actions.

This last point is the most important. Every meaningful decision that you make is an ethical trade-off, and this one is no different. When you continue to patronize media conglomerates, you are saying that what you get from them is worth the damage that you thereby do to the cause of an open internet. You may be right about the value of this trade-off, or you may be wrong, but you can’t in good faith continue to consume without at least thinking about it.

Ning nonsense is an opportunity for WordPress and BuddyPress developers

01-Feb-12

Another chapter in the Ning saga (see my previous posts on the subject): In the past few days, Ning has been sending out emails indicating that they’ll be wiping out non-premium networks in the course of the next couple weeks (see, for example, this blog post).

It’s no coincidence, of course, that I’ve gotten a number of emails in the last few days about support and/or paid consultation for Ning -> BuddyPress migrations, based on my free plugin Import From Ning. Unfortunately, I’m currently swamped with work, and I’m not available for active plugin support or for paid migration gigs related to Ning.

If you are a WordPress developer looking for work, this is a golden opportunity. For one thing, you can make a good amount of money helping folks to migrate their Ning data to BuddyPress, and generally helping to customize their BuddyPress installations. Most of the hard work is done for you: my Import From Ning plugin, while buggy and in need of some updates for recent versions of WordPress (in particular, the plugin has crummy error handling), has all of the logic you’ll need to parse Ning’s JSON files and process them for BP import. Even if you don’t know much about BuddyPress, you’ll find that the BuddyPress parts of the process are already spelled out for you. You might even learn something about BP along the way!

Furthermore, those developers who are really intrepid could take this opportunity to help the Ning/BP users more generally by taking over development on Import From Ning. If you are doing client work anyway, which may require fixing bugs and adding improvements in the plugin, why not contribute it back to the distribution version? By doing so, you’ll not only be helping to grow the BP community (and the cause of free software over proprietary services!), but you’ll be making a name for yourself as a contributor/committer to a popular plugin. In other words, it’s great publicity, and you’ll be creating a market for your services down the road.

If you are a WordPress or BuddyPress developer who is interested in receiving referrals for Ning migrations, and/or if you’re interested in making contributions to Import From Ning itself, let me know and I’ll add you to my list. (You can leave a comment below, or send me an email – boone <at> gorg <dot> es.)

IKEA standing desk

09-Jan-12

In the spring of 2011, I converted to a standing desk. At that time, I was unsure that I’d want to stick with the setup, and thus I didn’t want to spend the money on a proper standing setup. So my conversion to standing was effected by a motley collection of milk crates, thick books, and other implements of heightening culled from the corners of my apartment. More than half a year later, I’m still using and loving the standing desk, so I made the decision to get something a bit more permanent.

“Proper” standing desks – those that are built for the purpose – tended, in my research, to fall short in a couple of ways. The first is cost. Decent standing desks seemed to start around four or five hundred bucks, and go (way) up from there. The vagaries of New York living mean that I didn’t want to lay out huge amounts of cash on something that might not fit in my next place. I wanted something cheaper. The second shortcoming of manufactured standing desks is size. It’s pretty easy to find what they call “workstations”, which have a surface of about two feet squared. My 27″ monitor by itself requires nearly that much space, and I wanted surface area for writing, a second computer, coffee, etc, yet full-size tables seemed pretty hard to find. Lame surface size is related to my third problem with existing standing desks, which is the paltry storage underneath. I wanted lots of it, and commercially produced standing desks seemed, at best, to dedicate vertical storage to a printer (BOOO PRINTERS).

So I needed something fairly cheap, fairly big, and with a lot of storage underneath. A bit of trawling turned up this hack, which made a desk by combining a few different kinds of Ikea bookshelves. Unfortunately, that desk was too big for my space (I have about 66″ of horizontal space to deal with, and that setup requries a minimum of 73″). But it made me think I could do something similar using IKEA bookshelves.

Here’s the finished product:

And here are the details:

  • 3x BILLY bookcase – Two of these bookcases serve as the ends of the desk. Since I knew I’d have a bunch of additional space underneath, I bought a third, which is just slid underneath for extra storage.
  • 1x VIKA AMON table top – They didn’t have this in the same wood tone of my BILLY bookcases, so I got bright red instead.
  • 1x BILLY wall shelf – I needed something to raise my monitor and laptop up to eye level, and this gives me some nice desktop storage to boot. I couldn’t find something that spanned the full width of the table top, so I just centered this one, and used the extra space for speakers.

Total cost for these pieces was, as of yesterday, about $230+tax.

One of the big bonuses of using bookshelves as table legs is that I don’t need to worry about stability (like I would with regular table legs). The only fasteners I used were the four drywall screws I drove up through the bookshelves to keep the table top from sliding, and the two I drove down through the wall shelf to keep it in place.

If you’re looking to do something like this yourself, make sure you think carefully about height. I chose this combination in large part because the resulting table height (about 43″) works for me: in bare feet, standing on my anti-fatigue mat, my elbows are at almost exactly a 90 degree angle while typing. I’m between 6’3″ and 6’4″, so your ideal desk height may vary.

2011

01-Jan-12

A bunch of stuff happened in 2011.

Like 2010, 2011 was a year of transitions for me: in my relationship with academia, in the way I earn a living, in the way I present myself as a citizen-builder of the internet. Being a parent is the biggest transition of all, forcing me to put into perspective the ways I spend my energy and the ways in which I define myself and what has value to me. (This transition has been overwhelmingly a Good Thing.) Continuing to strive for the right balance in these areas will, I’m sure, be a hallmark of my 2012. (Thankfully, I have no plans to have a child or get married in 2012. A man needs a year off from major life events!)

Happy new year!