IndieWebCamp is a 2-day creator camp focused on growing the independent web

p3k


p3k-logo.png

pзk

pзk (pronounced "peek") is the name of the software that runs aaronparecki.com and caseorganic.com.

Screenshots

Writing a note (mini UI)
Writing a note (full UI)
Writing an article


Other

Source Code

While the core of p3k is not open source, many components are. Below is a list of the components used in p3k.

I am working to pull out more parts of p3k into libraries and will keep this list up to date as I progress.

Features

IndieWeb Support

Publishing Other Content

Aside from notes, articles and replies, I also publish the types of content listed below.

Sleep

Example: http://aaronparecki.com/metrics/2012/12/03/075900/

I've had the best luck with the Jawbone UP for tracking my sleep. I have logs now since November 2011 of how much I've slept every night.

The Jawbone app has an interface for adding a note to a sleep record. Here is a screenshot showing an example of adding a note to a sleep record.

Weight

Example: http://aaronparecki.com/metrics/2013/09/15/081800/

I use the Withings scale to track my weight. Through a series of convoluted steps, the data eventually ends up on p3k and is published here.

Currently every time there is a new measurement it results in a post on my site. I may change this to post once a week showing a small graph instead.

Pushups

Pushups example: http://aaronparecki.com/metrics/2013/11/28/143242/

I wrote a simple simple pushup-tracking app which makes POST requests directly to my server, creating these posts.

Backwards-Compatible Support

Notes vs Articles

  • Note: a note is plaintext only, HTML markup is not allowed. There is some auto-linking code that adds links around @mentions, URLs and hashtags. Any recognized URLs like images and video are embedded below the post.
  • Article: an article is a long form entry that supports any HTML.
  • See also: Semantics Of Article-Note Distinction

Storing External Content

When displaying external content on my site for reply-context and comments, p3k stores both the raw HTML and the parsed JSON for external pages on disk. Below is a screenshot showing how the folder structure maps to the URLs.

p3k-external-files.png

Local Nicknames

When writing a note, I often want to address people by a nickname rather than by full name or full domain name. (I don't think "@aaronparecki.com" looks particularly good in a post.)

I have a file called users.txt which contains a mapping of local nicknames to profile info including full name, website and avatar URL. I call this a "local" nickname because it may or may not be a nickname that the other person actually uses for themselves or exists on a silo. In practice, it mostly consists of Twitter usernames, however.

Sample data:

@aaronpk      http://aaronparecki.com http://aaronparecki.com/images/aaronpk.png Aaron Parecki
@caseorganic  http://caseorganic.com https://twimg0-a.akamaihd.net/profile_images/1788860814/kk-caseorganic_reasonably_small.jpg Amber Case
@tantek       http://tantek.com http://tantek.com/photo.jpg Tantek Çelik 
@t            http://tantek.com http://tantek.com/photo.jpg Tantek Çelik
@snarfed	http://snarfed.org/	https://pbs.twimg.com/profile_images/2812992290/be21b6e4df4b499a98e87413b355c657_bigger.jpeg	Ryan Barrett

Note that in the case of @snarfed, his twitter account is actually different.

Issues

  • Fixed-column schemas are annoying to deal with and extend
  • Since some of these photo URLs are twitter URLs, they often change and many are already out of date

See Also

nicknames-cache

Database

p3k uses a database as a cache and to quickly query lists of posts by category, tag, date or by other meta data. No actual post content is stored in the database, the post content is read from disk when needed. The database can be regenerated from the raw files on disk with a script, so there is no worry if the database is suddenly deleted or corrupted.

Schema

posts

The posts table holds the primary meta-data for all posts on the site.

  • `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  • `category` varchar(255) DEFAULT NULL,
  • `type` varchar(255) DEFAULT NULL,
  • `permalink` varchar(255) DEFAULT NULL,
  • `filename` varchar(255) DEFAULT NULL,
  • `published` datetime DEFAULT NULL,
  • `updated` datetime DEFAULT NULL,
  • `tz_offset` int(11) DEFAULT NULL,
  • `timezone` varchar(255) DEFAULT NULL,
  • `latitude` double DEFAULT NULL,
  • `longitude` double DEFAULT NULL,
  • `client_id` varchar(255) DEFAULT NULL,
  • `deleted` tinyint(4) NOT NULL DEFAULT '0',
  • `draft` tinyint(4) NOT NULL DEFAULT '0',

Indexes:

  • KEY `published` (`published`),
  • KEY `filename` (`filename`),
  • KEY `post_type` (`type`),
  • KEY `category` (`category`),
  • KEY `category_published` (`category`,`published`),
  • KEY `category_type` (`category`,`type`)

tags

Each tag has an ID and is stored in the tags table.

  • `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  • `tag` varchar(255) DEFAULT NULL,

Indexes:

  • KEY `tag` (`tag`)

post_tags

This table links posts to tags.

  • `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  • `post_id` bigint(20) DEFAULT NULL,
  • `tag_id` bigint(20) DEFAULT NULL,

Indexes:

  • UNIQUE KEY `post_id_2` (`post_id`,`tag_id`),
  • KEY `tag_id` (`tag_id`),
  • KEY `post_id` (`post_id`)

clients

The clients table holds a list of all micropub clients that have created posts.

  • `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  • `client_id` varchar(255) DEFAULT NULL,

Indexes:

  • KEY `client_id` (`client_id`)

syndications

The syndications table contains syndication URLs for posts.

  • `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  • `post_id` bigint(20) DEFAULT NULL,
  • `service` varchar(255) DEFAULT NULL,
  • `syndicated_url` varchar(255) DEFAULT NULL,

Indexes:

  • KEY `url` (`syndicated_url`),
  • KEY `post_id` (`post_id`)

This can be used to find the canonical URL of a syndicated post given its URL on Twitter or Instagram.

Storage

All content in p3k is stored as files on disk.

There is a top-level folder for each post type, articles, notes, replies, events, metrics, travel, presentations. (If I had to do this from scratch, I wouldn't have made this distinction at this level).

Each folder contains subfolders for the year and month.

For everything except metrics, the structure is:

  • YYYY/mm/dd-n.md where n is the nth post on that day.

For metrics, the filenames are the full timestamp:

  • YYYY/mm/dd/HHMMSS.md
2014-05-25-aaronpk-articles-filesystem.png 2014-05-25-aaronpk-notes-filesystem.png 2014-05-25-aaronpk-metrics-filesystem.png

If there are any associated photos or files for a post, they go into a subfolder with the same name as the base name of the file. In the "notes" example above, the photo attached to the "08-4.md" note lives in a folder named "08-4".

Working On

The things I am currently implementing in p3k:

Error retrieving content from GitHub. Malformed JSON was returned from the API.

URL is: https://github.com/aaronpk/p3k/issues?labels=priority%3Ain-progress

Itching

These are a collection of annoyances that have respective features / improvements. As their annoyance level bubbles to the top, they're likely to become concrete "Working On" tasks.

Show photo thumbnail in reply context

as shown here http://indiewebcamp.com/reply-context-examples#reply_to_a_photo

Support reposts, or featuring external content in my main feed

Create buttons to POSSE posts after they are created

Occasionally I find myself posting a note and afterwards wishing I had clicked the "POSSE to Facebook" checkbox in my interface.

When viewing a note, I should have a button I can press to POSSE to any of my POSSE destinations. I guess this will involve an intermediate interface element so that I can edit the text that will be sent to the POSSE destination.

2 comments

New "like" post type

Need to be able to create a "like" post on my site.

http://aaronparecki.com/notes/2013/06/23/4/indieweb

Will also be used when I import (or PESOS) my likes/favorites/etc from silos:

  • Tweets
  • Facebook posts
  • Google +1 button
  • Hackernews upvotes
  • others?

Would be a breadcrumb of my travels over the Internet.

Need Further Thought

Checkins

I have been using Foursquare consistently for a number of years now, and it is the authoritative source of every venue I've been. I know that if I have never checked in somewhere before on Foursquare, I actually have never been there before.

While my Foursquare feed is currently public, I'm reconsidering whether I want my "IndieSquare" feed to be completely public. I may end up being more selective about the checkins I make public instead, and keep my full checkin history private.

Examples of public checkins often include a short note from me along with the venue for things like checking in to a venue for a public event, or checking in somewhere to say I'm going to be hacking there for a while inviting people to join me. When I check in to lunch two blocks away from my office, it's not that I don't want anyone to know I'm there, it's just that probably nobody cares and there usually isn't anything actionable that would come from them knowing anyway. Usually I'm getting something to go and don't have time to stay and talk anyway.

IndieSquare

Foursquare provides:

  • a push API so I can pesos checkins to my site in real time
  • lots of my friends still use it
  • the app still provides fun tidbits when I check in, like "you've been here 5 weeks in a row", etc
  • searching for venues is difficult to implement from scratch, and I'm not entirely happy with the OSM data, so using foursquare venues continues to be highest quality

Really getting annoyed that when Foursquare venues are renamed, merged or deleted, my own history is changed.

  • Figure out how to represent a "checkin" on my own site (see Creating content on the Indie Web for more thoughts)
  • Figure out how to store venues on my site (venue IDs, nice slugs, ???)
  • Build a basic interface for viewing "checkin" data
  • Syndicate out to Foursquare and possibly Facebook (although Facebook recently deprecated checkins in favor of attaching venues to notes)
  • Repurpose the Checkie app to search my site for venues and post checkins to my site first
  • Download all Foursquare history and create checkins on my site retroactively

Location

Since I carry an active GPS tracker at all times, I collect a large amount of location data. It is not automatically organized into "trips" or anything, it's just a raw stream. I've been considering various ways of publishing this for some time.

Currently I publish my current city as well as time zone of wherever I am on my home page. I do not yet have a feed available.

I'm considering publishing a new "location" post any time I change cities (or possibly also large neighborhood). Here is an example of publishing my city automatically to Facebook: http://www.flickr.com/photos/aaronpk/6962452588/

There are other non-venue locations I may want to publish, such as when I get into a neighborhood I haven't been to in a while. Ideally my phone would detect automatically when I've entered a new area or an area I haven't been to in a while. Probably I would want it to prompt me before publishing anything publicly. I could receive a push notification saying something like "It looks like you're in NW Portland for the first time since August! Publish this?"

Open Source

While the entire p3k stack is not open source, I have open-sourced many of the components. I've chosen to provide components of the stack rather than the whole thing because in reality nobody is going to want to use the exact same workflow I have built. Instead, components of my site can be re-used by others in their own way.

See #Source Code above.

Contents

Retrieved from "http://indiewebcamp.com/p3k"