Building a baby photo site with WordPress

My wife and I just had our first baby, which is the occassion for much nachas and, by extension, picture sharing. Facebook is, for better or for worse (emphasis on the latter), the de facto place for such sharing to happen. For a number of reasons – a desire to be somewhat selective about who sees my family pictures, my Project Reclaim sensibilities, the fact that I don’t have a Facebook account and generally think that Facebook is an evil company – I don’t want to use FB for this purpose. As in the case of my Twitpic-like photoblog, I figured I could use WordPress to set something up that was nearly as seamless as Facebook, or Google+, or Flickr, or whatever.

The criteria

There were a few things I wanted out of the baby site.

  1. Easy (or zero) login for users
  2. Control over who has access
  3. Optional email notification for new content
  4. Easy, javascripty gallery browsing

When I started, I was pretty sure that I’d be able to get all of these things pretty easily, using existing WordPress plugins. I was both right and wrong about this: plugins exist for all of these purposes, but none of them were very easy to implement. As a result, I ended up building several pieces from scratch. I’ll go through each of the criteria, talk a bit more about what I was looking for, and then say something about how it was achieved. By doing this, and sharing the code (spoiler alert:, I’m hoping that I can help others with similar sensibilities to get started on their own sites.

Non-sucky registration and login

I love WordPress, and I understand the important reasoning behind the decisions that led to the design, but WP’s user registration system sucks. I didn’t want just anyone to be able to create and activate an account. I didn’t want users to have to click an activation link. I didn’t want users to have randomly generated passwords that would need changing later on. And I wanted users to have the option of logging in a non-WP way.

Several of these problems could be solved by using Facebook logins. I’m not willing to give my photos over to the horrific FB leviathan, but I’m happy to piggyback on their login APIs if it will save my family and friends a few headaches. I wanted my users to have the option of clicking a single button that would give my site the ability to provision them based on their persistent Facebook login.

I started by looking at some popular Facebook Connect plugins from the plugin repository. I didn’t really like them. Most were linked to the Comments section of blog posts, while I wanted to use the logins for overall site access. Most were dependent on Javascript for logins, while I wanted to handle logins on the server side. Most used an outdated version of FB’s API (or at least of the PHP API classes that FB offers). And, to be blunt, most were too much of a mess, having been retrofitted many times over, and as a result next to impossible to extend. I tried modifying one or two of the more popular FB-WP plugins to do what I wanted, but I ended up writing so much garbage spaghetti code that I decided to cut my losses and start from scratch.

So I boned up a bit on the FB API, and wrote a small plugin that I call Wally Login. Together with the registration page template from my custom theme (a child of TwentyEleven), it does a couple of key things.

Your choice

Your choice

  • Rudimentary access control · If a non-logged-in user tries to visit any page on the site (other than the registration page), he is redirected to the Register page.
  • FB login integration · If a user clicks the “Log me in using Facebook” link, they’re directed to the FB authorization page for my website (which is registered as a Facebook app). There, they’re asked to approve the app – a one-time process – and are then returned to my site. Based on the display name, email address, etc that I get from FB, I create a WP user corresponding to the FB account. On future visits, approved users who are logged into Facebook will be automatically logged into my WP site whenever they visit it (an important point, because FB cookies are persistent over browser sessions, while WP logins, by default, are not). As a result, in the best-case scenario, a user will authorize their FB account with my site one time, and will never again have to think about authorization on Wally’s page.
  • A customized WP registration process · If users opt not to go the FB route, they can create a WP account directly on the site. I wanted to avoid sending users to an unthemed wp-login.php or wp-signup.php page, so I cribbed a few lines of code from BuddyPress and made my own registration and login dialogs. Wally’s site is part of a larger WP network, but I wanted to bypass WPMS’s built-in registration stuff (which requires users to activate their accounts, and is thus generally too hard for newbies to grok). My custom registration therefore creates the user directly (with wp_insert_user()), using a password that he provides, and skips the activation email. (By bypassing account activation, I’m removing an important spam prevention tool. More on that in the next section.)
  • Customized email notifications · Because I’m not using the built-in registration process, I needed to write my own email notifications for account applications and approvals.

If you decide to use my code, keep in mind that it’s not particulary beautiful. I wrote it for my own use, which means that it will take a bit of elbow grease to get it to work on your own site. In particular, if I were writing something for more general distribution, I would not be so reliant on a theme template as I am here. But if you’re looking to create a site like mine, this code is a great place to start – especially the FB integration stuff, which has made the registration and login process about as smooth as it can get.

Access control

The final important thing that the Wally Login plugin does is to provide me (the site admin) with control over who has access to the site. There are a couple ways I could have approached this issue. One is to whitelist users ahead of time. The problem with this is that I’m bound to forget some names, get email addresses wrong, and run into other problems that stem from my unfortunate lack of omniscience. Another strategy is the invitation code. When unique to the individual, this method suffers from the same drawbacks of the whitelist; when non-unique (ie when everyone uses the same invitation code) it takes away much of the security, as the code can be passed around quite easily; either way, invitation codes are clunky, easily misplaced, and all too often mistyped.

Thanks for applying

Thanks for applying

As a result, I ended up going with a third option: an application and approval process. Here’s the idea, conceptually. Anyone who wants can create an account on my site (either through Facebook or natively; see the previous section). However, the account does not actually allow access to the site unless the account is also approved by the administrators. Thus, after the initial application, two emails are sent: one to the applicant saying “thanks for applying, please be patient”, and one to me saying “there’s a new applicant, please approve them”. Then I go to my approval interface and click the Approve button (if I want), which marks the user as approved in my database and sends them an email saying “You’re in!”

Here’s a brief description of how it works technically. All applicants have a WP account created for them. Every new account is marked, at the time of creation, with user_status = ‘2’, and I make sure that no page other than Register can be viewed by an account with user_status = ‘2’. In this way, I am turning the idea of activation around a bit – natively, WP makes the user do the activation, but in my case I do it. The admin tool I use to activate users is my Unconfirmed plugin, designed for a slightly different purpose but quite at home here. (For technical reasons, Unconfirmed needs users to have activation keys; thus Wally Login also generates some dummy keys during the user creation process so that Unconfirmed will work right.) Unconfirmed, in turn, does the work of flipping user_status to 0 upon approval.

Taken together, Wally Login and Unconfirmed (with custom WP registration, FB integration, user approval by admin, etc) has given me a comfortable level of access control, without making the process unduly difficult for my users.

Email notification for new content

One of the biggest drawbacks of creating a standalone picture site instead of using an all-purpose social network (in practice, this means Facebook) is that the standalone site is likely to be forgotten. FB collects all of your network’s activity into a single stream; it’s highly unlikely, on the other hand, that Wally’s site will become part of anyone’s daily routine, so that they stop by to check for new content. For that reason, good email notification of new content is essential to making the site work.

Dead simple email subscription

Dead simple email subscription

I first tried using the popular Subscribe2 to handle these notifications. But I ran into a bunch of problems. For one thing, I didn’t like that S2’s subscription management happened in the Dashboard – I want to keep my users on the front end. S2’s category-based subscription is too complicated for my site, where people are either going to want to subscribe to all posts or to none at all. And the widget that comes with S2, for display on the front-end of the site, is pretty much atrocious. (Sorry. The rest of the plugin is nice. But that widget sucks.) At first I tried solving these problems just by building my own widget for S2, one that would tell the user whether he was currently subscribed, and show an Unsubscribe/Subscribe button, as appropriate. But, given the structure of S2’s data (which is somewhat arcane, and in any case far too complicated for my purposes), it ended up being a lot harder than it should have been.

So – wait for it – I wrote something from scratch. It is dead simple. Two parts: (1) a widget, which does exactly what I describe in the foregoing paragraph; and (2) hooks into publish_post to send an email to all subscribed users (along with some gentle checks to make sure dupes are not sent). This plugin has no admin UI and no options, because I don’t need any of those things.

Pretty galleries

Since the main point of the site would be to look at lots of pictures, it was quite important to have an easy, pretty way to do so. By “easy” I mean, primarily, navigable by keyboard; by “pretty”, I mean, primarily, bigger than the content area of a typical blog post. Less important, but still desirable, was the admin interface: I wanted it to be easy to upload lots of pictures at once, to add captions and other metadata if necessary, and to turn it all into a gallery that would look good on the front end.

Pretty, easy

Pretty, easy

You know the drill: I tried a couple of the more popular free plugins, but all of them were annoying in one way or another, and each one was way overengineered for my meager needs. I was especially disappointed by the back-end admin for the popular gallery plugins, which I found lugubrious, unintuitive, and impossible to extend. After some consideration, I decided that I actually preferred WP’s native Add Media interface for uploading photos and adding metadata, and that I was perfectly happy with the way that WP’s gallery shortcode displayed content on the front end, at least when viewing thumbnails.

So the only thing I really needed was to implement the javascript that would allow for keyboard navigation and lightboxing of gallery photos. Thanks in part to his extremely uncreative and literal plugin naming schema, I found Viper007Bond’s jQuery Lightbox For Native Galleries plugin. It does almost exactly what I want, right out of the box.

I did make a few minor mods, though. First, the plugin is a bit greedy in the way that it filters the output of get_attachment_link(), which was either breaking things (as in the case of comment_post_redirect on attachment posts) or making it hard to display links to the attachment page instead of the raw attachment file. The former problem I solved with a filter; for the latter problem, I was a bit lazy, so I modded the plugin itself in addition to adding an explicit ‘lightbox’ class to attachment links. This combination of hacks makes it work perfectly for my purposes.

Odds and ends

A little bonus

A little bonus

With my absolute requirements met, I was able to add a few other goodies to the site. My theme is a child of Twenty Eleven, which I’m pretty much using as-is. But I’ve added a few fun bits. First, on each attachment page, I added Download links, so that users could download images of various resolutions for printing or editing. I messed with the WP Admin Bar so that users coming from Facebook wouldn’t see Log Out and some other inappropriate links. And under each thumbnail in Gallery view, I’ve added Download/Comments links, so that users could bypass the jQuery lightbox and go straight to the attachment permalink if they wanted.

It took some work, but I think I’ve ended up with a site that is nice to use and easy to maintain, without resorting to the extreme discomfort associated with Facebook. Hooray!

17 thoughts on “Building a baby photo site with WordPress

  1. Matt

    This is fantastic, Boone. I (and many others) are in your debt. Thank you for putting this post together and sharing your code!

  2. Matt

    I’ve spent part of the day getting all of this working on my own site. It’s just so great — as you know, I’ve been looking for something like this for a long time, and I’m enormously grateful to you for putting it all together.

    A few additional notes on customization to others setting up a similar site using this code:

    1. The entire codebase can be downloaded from github, but one should obviously upload it to a WordPress install. The folders that need to be copied over after being unzipped are the theme and plugin files in wp-content.

    2. Much as I love WallyG and the WallyG themes/plugins, I didn’t want my own site to mention Wally’s name in connection with photos of my own son. In order to alter such messages, users should open page-register.php and find/replace with the designation of their choice. The same should be done for the wally-login.php file in the wally-login plugin (search for “Wally’s” in that file). When doing this find/replace, be careful not to overwrite any instances of “wally” that appear in function names.

    3. If one uses “More privacy options,” as I do, privacy should be set to either allow everyone or to allow normal visitors/block search engines. Don’t worry — Boone’s registration template in the theme forces users to log in.

    4. After activating the theme, one needs to create a page called “Register,” using the “Register” template, to activate the login functionality described above.

    5. As Boone writes above, photos should be added to posts. But to get the Download/Comment link on the homepage as he describes it, they should be added to the post as thumbnails. Note that there are some gallery settings on the image uploader, and also that there is a menu on the right side of the post box, titled “Format” that allows one to choose “gallery” if one wishes. However, publishing a post in “gallery” prevents individual photos from being accessed/viewed through lightbox on the home page.

    I hope I haven’t screwed anything up in the above directions, Boone — please feel free to edit my text or to make corrections below if I have.

    Now, one question:

    Do you upload and tag photos individually? Or is there a way to add/tag a group of photos at once?

    At any rate, thanks again for all of this work. This is the part of #projectreclaim I was most looking forward to, in part because I decided long ago that I didn’t want to posts photos of my child on proprietary sites.

  3. Boone Gorges Post author

    Thanks, Matt and Andrea 🙂

    Matt – You should be able to upload many pictures at a time, as long as you are using the Flash uploader. Just select multiple files (using Cmd, Ctrl, or Shift) on the Browse dialog. I haven’t been tagging photos individually – just tagging the posts that contain the galleries.

    As for your (5): Not sure I understand what you mean about “added to the post as thumbnails”. If you mean the image size that you select when you initially upload the pictures, I think you’re mistaken – I’ve used “Large” on all my photos. The gallery markup is created independently of that selection. You’re right that selecting the Gallery post format has the effect of disabling Lightbox view on the homepage. But for me, the Download/Comment links show up fine on the home page when I use the Standard post format.

  4. jean baptiste durand

    Hello Boon,

    First of all BRAVO for your baby.
    This is the most important thing in a lifetime (I have got twins girls so I can tell it).

    I’m a Buddypress user and I am waiting to see if BP 1.5 is going to solve the VERY IMPORTANT PROBLEM of PRIVACY that I have.
    I want the members of my BP site (The Club) to each have a (uniform themed) private blog that could be read only by the people they accept.
    private blog readers should be following these requirements:
    – facebook friend or member of a facebook group of friend or google plus specific circle member
    – any user invited or accepted by request by the blogger

    PLUS Each posts from different blogs should be readable ONLY by users if they have been previously selected to access specific post categories

    I have a baby and I want to show the photos and youtube videos and blabla to my family and my very close friends only
    so, I write a blog post on my personal blog
    then I select the post categories : “family only” + “personal life”

    Readers that are :
    a) allowed to access my blog
    b) allowed to access my categorised posts ( “family only” or “personal life”) will see it.

    I will end up telling you that all this should be done in the front end (wp dashboard is not for grandmothers),
    I currently generate the blogs post by gravity forms (wp dashboard is not for parents writing posts about their baby)

    goal: 3 clics and no spam.

    I watched very carefully your presentation of BP 1.5 at the WPNYC conferences
    and all I understood is that there will be a level of privacy in BP groups.
    In BP 1.2 a blog is always visible and 2 options allow blog to be visible or not in google + BP.

    Maybe you have some clues for this…
    I will wait for your answer if you find some time for my request.

    Best regards from the South of France
    Courage for the baby nights

    JB Durand

  5. Matt

    You should be able to upload many pictures at a time, as long as you are using the Flash uploader.

    It’s that last part that is tripping me up, as I seem to have only the browser uploader as an option. Any ideas how you would upload photos through the browser uploader (and/or force the flash uploader), or can batch uploads only be done through the flash uploader?

    I did a bit of googling on forcing the flash uploader, but the solutions out there seem a little convoluted and, uh, forced to me.

      1. Matt

        No, but I’ll give that a shot, even if it reeks of “This site is best viewed in Netscape Navigator 2.0” What’s strange is that I don’t even have the option in Chrome to enable the flash uploader.

    1. Boone Gorges Post author

      Bizarre. Are you running the latest version of WP? I know that some improvements have been made to the process in WP 3.3 (currently in beta). Maybe you can try that?

  6. Matt

    Okay, Boone. So, I’ve decided not to worry too much about the Flash uploader for now. What I’ve discovered is that I can upload files one-by-one. The key thing is that those photos do not need to be inserted into the post. Instead, one adds the shortcode [gallery] to the post. That will create a gallery based on all photos uploaded to that particular post, even if they weren’t inserted into it.

    So, that’s great. I can now add photos. However, what happened next is that I received an email notification announcing that the Gorges family had just uploaded photos to my site!

    Can you point me to the file that holds your dead-simple plugin? I hate to say it, but maybe the widget needs some options!

    1. Boone Gorges Post author

      I hate to say it, but maybe the widget needs some options!

      Patches welcome! Building options takes 10x as long as hardcoding.

      Look in wp-content/plugins/bbg-subscribe2-widget/bbg-subscribe-widget.php.

      1. Matt

        Cool — thanks!

        I might just take you up on that patch challenge. It would be a good learning experience.

        In the meantime, I just revised the hardcoded info. I think I’m all set to go!

  7. Matt

    Found another hard-coding issue — people using this code have to replace the personalized info in wally-login.php with their own contact info.

    Here’s a question, though: when I tried to visit ../wp-admin/users.php?page=unconfirmed , I saw an error message saying “You do not have sufficient permissions to access this page.” This is despite the fact that I’m logged in through an admin account and can view the dashboard if I just visit wp-admin.

    Is there another way to view unconfirmed registrations besides visiting that link? And do you have any idea why it might not be working? I’m using WP 3.2.1

    Thanks in advance for your help.

  8. Steve

    Hi! Very interested in your blog plugins – I see that hasn’t been updated in 9 months in git. Are you planning on maintaining this any further? Hope so! Thanks!


Leave a Reply

Your email address will not be published. Required fields are marked *