<![CDATA[iyWare]]>https://iyware.com/https://iyware.com/favicon.pngiyWarehttps://iyware.com/Ghost 1.20Mon, 22 Jan 2018 15:08:51 GMT60<![CDATA[The Plugin Statistic that Matters]]>

I've written only one WordPress plugin that was generic enough to be released in the plugins repository. That plugin is called "My Posts" and it trivially solves a problem that was rather significant in one of my projects. I say it trivially solves it because the entire plugin

]]>
https://iyware.com/the-plugin-statistic-that-matters/5a513274533fe1b5bec542c7Sat, 23 Apr 2016 16:38:32 GMT

I've written only one WordPress plugin that was generic enough to be released in the plugins repository. That plugin is called "My Posts" and it trivially solves a problem that was rather significant in one of my projects. I say it trivially solves it because the entire plugin is comprised of only 11 lines of code (and funnily enough 10 lines of documentation, 9 lines of versioning, and 11 lines of license information). Anyways, I've written about this plugin previously, today I want to talk about statistics.

What Makes a Plugin "popular"?

I'm sure that every developer has a different metric for what success is when they release something. For some it's the fact that the project is complete, for others it's hearing that it's useful, for others it's download statistics, and for others still perhaps it's doors that are opened as a result.

These are all great things, and I wouldn't necessarily advocate one over the other. However, marketplaces tend to favor one particular statistic over all others: total downloads. While other statistics are often leveraged (user ratings, active installs, etc...) this one is generally given priority treatment. If you need evidence of this look no further than Themeforest, the Moodle plugins directory (click "log in as Guest" if prompted for authentication), or the WordPress Plugins page. In fact, even if a market doesn't have a "top downloads" list you can bet that the total downloads for a product will be listed somewhere.

In fact, Google Play seems to be about one of the only markets that doesn't just rely on a download count, but instead takes a holistic approach for ranking a "top" app. I realize, of course, that this isn't feasible (or practical) for all applications. Various markets try to offset this by a variety of methods including things like "top downloads by [day|week|month]" to give some insight into trends or a "featured" selection - essentially showcasing a product that is really good at what it advertises but isn't necessarily downloaded a lot. Of course the end-goal of a "featured" list is to get that product downloaded a lot so that it appears in the "top" list.

Introducing "Active Percentage"

Now, I'm not going to advocate that total downloads is a bad metric in itself, but I'm going to suggest one that I think is a better metric for both developers and markets. That metric is "active percentage". Now, there are lies, damn lies, and statistics, so take this with a grain of salt. Here's the formula I'm advocating:

AP == Active Installs / Total Downloads

This essentially tells you "of the people that know of or tried your product, how many are actively using it". Now this isn't possible for a number of projects, but it is possible for some including WordPress and Moodle.

Active Percentage Examples

Let's take a look at a few examples, starting with my "My Posts" plugin: as of writing the plugin has 317 downloads, which is not a lot (in my opinion) and it has 60+ Active Installs.

My Posts

AP == Active Installs / Total Downloads
AP == 60 / 317
AP == 18.93%

18.9% of people who download my plugin actively use it. Now, again, to me that's not a very high percentage. That's a greater than 80% abandonment rate. But, and this is big, we have no idea how that stacks up in the marketplace. Maybe 18 is pretty high, maybe it's abysmally low. Let's take a look at some of the other popular plugins in the WordPress plugins directory. Now, there's one flaw here and that is that the plugins directory only reports up to 1 million+ active installs, so anything with over a million active installs (say 2 million or 10 million) is unreported so we are limited to looking at popular plugins with less than a million active installs. We're also going to ignore the + which could significantly throw of some statistics (999,999 is reported as 900,000+ deviating by practically 10%).

Page Builder by SiteOrigin

AP == 900,000 / 3,963,901
AP == 22.70%

Disable Comments

AP == 800,000 / 2,559,729
AP == 31.25%

WP Multibyte Patch

AP == 800,000 / 2,184,427
AP == 36.62%

[Black Studio TinyMCE Widget](Black Studio TinyMCE Widget)

AP == 800,000 / 2,949,696
AP == 27.12%

Google Analytics Dashboard for WP

AP == 800,000 / 5,133,130
AP == 15.59%

Those are the top 5 listed popular plugins with less than a million active installs, now let's look at the bottom 5.

Check Email

AP == 10,000 / 58,813
AP == 17.00%

New User Approve

AP == 10,000 / 155,479
AP == 06.43%

WordPress ReCaptcha Integration

AP == 10,000 / 59,765
AP == 16.73%

WP Social Sharing

AP == 10,000 / 73,171
AP == 13.67%

Latest Tweets Widget

AP == 10,000 / 92,484
AP == 10.81%

Now let's get an average for top WordPress plugins: 19.79% is the average of those 10 plugins. I think it's reasonable to say that if your WP plugins has an Active Percentage of 20% then you're in-line with the top plugins. Now, there's not necessarily a correlation between these two, but let's grab 10 random plugins and evaluate those. We're going to grab the first plugin from the approximate top 10 results of the "popular tags" word cloud that aren't listed above. We're going to rely on the generation of the word cloud and my inability to distinguish font-size to provide us some randomness. The tag being popular doesn't indicate that the plugin itself will be, it just means that there are a lot of plugins in that category.

Widget Wrangler

AP == 1,000 / 33,807
AP == 02.96%

WordPress Shortcodes

AP == 10,000 / 248,318
AP == 04.03%

E-MAILiT Free Sharing Buttons

AP == 9,000 / 281,095
AP == 03.20%

WPSSO

AP == 10,000 / 1,472,313
AP == 00.68%

MailPress

AP == 9,000 / 310,781
AP == 02.90%

Customize Woocommerce Shop

AP == 60 / 368
AP == 16.30%

Social Media Feather

AP == 100,000 / 1,057,726
AP == 09.45%

Simple Google News DE

AP == 500 / 2,009
AP == 24.89%

Slider SEO

AP == 10 / 131
AP == 07.63%

WP Accessibility Helper (WAH)

AP == 10 / 77
AP == 12.99%

Now the average of these 10 random plugins: 8.50% which is significantly lower than the top downloaded plugins. There are a number of things that can cause this (like bias toward top plugins) but I think it's safe to say that if your plugin is performing around 8% AP then you're a run-of-the-mill plugin.

Conclusion

So what can we do with this? Obviously I'm not advocating abandoning total downloads in favor of this- especially if your revenue comes from downloads! What I'm suggesting is that this metric can be added to your toolbox to help give you an overview of how your plugin is performing. Total downloads per day is great, but add in a second graph of AP-per-day and you can get a view of if your total market is growing or shrinking. See if you're trending toward 20% or toward 8%.

Abandonment is a key metric for a lot of recurring revenue markets like SaaS, subscriptions, or even ad-based generation. Abandonment might affect your bottom line in download-based revenue as well. Think of it this way: which plugin that does "X" is someone likely to recommend? The one they're using, not the one they used.

]]>
<![CDATA[Learning is the Goal]]>

"Our hypothesis was right."

First, a Story

I've been a judge for the Intel International Science and Engineering Fair (ISEF) in Asia, I think oh... about 5 times now. In fact, I've been the judge of projects that have gone on to the US and placed and even

]]>
https://iyware.com/learning-is-the-goal/5a513274533fe1b5bec542c5Mon, 04 Apr 2016 02:57:51 GMT

"Our hypothesis was right."

First, a Story

I've been a judge for the Intel International Science and Engineering Fair (ISEF) in Asia, I think oh... about 5 times now. In fact, I've been the judge of projects that have gone on to the US and placed and even won. I've seen students offered scholarships to universities based on their work, but one thing I've never seen is someone say "my hypothesis was wrong."

I've seen project records and logs which might, might, document some adversity. But fortunately for the student it's always overcome. This is particularly true of the engineering projects. The closest thing I've ever seen to someone saying their hypothesis was wrong is when they follow up with "the results were even better than we predicted!"

Now, full disclosure, I was picked as a judge because of my technical background- specifically computing. There are some projects to which I am ignorant of the content (especially anything dealing with chemistry) but I am familiar enough with the framework of the scientific method to know what questions to ask, and when answers don't pass the sniff test.

Additionally, in the world of engineering the refrain might as well be "results or it didn't happen." I've literally had sessions go like this:

  • Student: here's our widget it does X and Y.
  • Me: show me X
  • Student: [tries X- fails]
  • Me: show me Y
  • Student: [tries Y- fails]
  • Student: it's worked every other time! I don't know what's going on! Believe me this thing work! Please don't judge based on the demonstration, we promise it works.

The Problem

Now, perhaps you think that I'm berating these students. This post is is an unmerited attack on high school students who are just participating in a science fair, and trying to win.

That's the problem. Well, let me be more specific: we're the problem. We (adults in education) have set these students up for success. Success, or passing, or winning, or the opposite of failing- is what matters most. To the point that (in their minds) success must be achieved by any means. Steal code (by which I mean use without attribution*), falsify scientific data, change your hypothesis after you get your results, BE RIGHT.

Of course, if you look at the rubric for a science fair it's all based on method- not results. No where does it say "Was your hypothesis right? +10 points" But of course, you know that there's theory, and then there's practice. What other event, in all of a child's schooling, are they given full credit for an incorrect answer? If I recall correctly we spend a fair amount of time attacking the "A for effort" straw man.

Even so-called formative assessments (quizzes, etc...) are awarded points and logged for value with the so-called summative assessments. In fact it's entirely possible, generally speaking, to fail a class because enough formative assessments have been "failed", results of the summative assessment be damned!

No, we demand perfection. Straight A's. 4.0 4.1 4.25. We demand better than perfection. And at the end of the day (or 13 years...) we choose the best student and parade them out in front of all the other students to give a speech.

The Solution

Well, unfortunately for you, dear reader, the solution while fairly obvious is both nuanced and outside the scope of this post. Instead I offer you the remedy.

The Remedy

Perhaps I'm being pedantic, but I believe that there's a difference between a solution and a remedy. A solution is a top-down, functional, calculated fix. A solution is indisputable, absolute, and THE right way. We've seen plenty of solutions in education, and we seem to be fixing our way into more and more problems. This is what Will Richardson calls "doing the wrong thing the right way."

On the other hand, a remedy is medicinal. A remedy is a holistic approach to a number of symptoms that attempt to address an underlying cause (or causes). A remedy takes time, re-assessment, and may cause other symptoms to flare-up during application but ultimately leaves a system in a better state than it started.

Here's my proposed remedy: document your failures. Don't regale your students about people like Einstein or Elon Musk and their failures on the road to success. Don't merely give them trivium about how many times Edison failed before he invented the light bulb. Because you're still setting the goal at success, and frankly (given the current system), if you told you students to invent the light bulb they'd only get one shot at it before they got an "F".

Adam Savage says "failure is always an option." but that's kind of a lie. A certain kind of failure is allowable, a tolerance or margin of error if you will. Let me put it this way. Was there ever a week when a new MythBusters was supposed to air, but instead the title card read something like,

The new episode of MythBusters will not be airing tonight as Jamie and Adam went way over budget and time trying to solve an engineering problem. They still haven't figured it out, but hopefully we'll be back next week.

No way. Failure, was not an option. Probably contractually so. And that's OK.

But showing your students that the MythBusters fail is not- because the goal is still success.

So, instead of documenting the failures of others (who are probably successful now), I challenge you to document your own failures. Not your stumbling blocks on the way to success, but rather things that you just straight up failed at. Didn't work. Maybe even cost you some valuable time or money for which there was no reconciling.

Students need to learn that failure is OK before they learn that it's just a stepping stone to success. We tend to jump straight to success and then tell them that failure is OK. This leaves them incapable of understanding how as they are diametrically opposed.

A clarification

I've talked a lot about not setting the goal on "success". I can imagine that some might take issue with that, so I'd like to clarify. The success that I'm saying we should avoid is "do what it takes to get straight A's" success. It's the success that causes someone to lie about their science fair project.

At the same time I'm advocating the acceptance of failure. Assuredly I'm not saying to allow a competent student to be content with work below what he is capable of (notice I didn't say a grade letter?).

No, the goal I'm talking about should be on learning. You might call this "success" and, well, that's just semantics. The point is that by ignoring failure, or covering it up, hiding it, it becomes impossible to accept the failure. Without accepting failure it is impossible to analyze and adapt. Without this analysis or reflection, it is impossible to learn. Learning is the goal.

Conclusion

Ultimately students learn what they are taught, and this comes primarily by observation. We are teaching students to fear failure. We are teaching students to be prideful. And we are teaching students to do what it takes to "succeed."

It's time for a remedy. Share your failures with your students.


* I have no problem with using other people's properly licensed code. There's no need to reinvent the wheel. I do have a problem with taking code, removing authorship and copyright and telling me it's yours. But I empathize due to the environment that makes one think that this is the only way to "succeed."

]]>
<![CDATA[My Laser-Cutter Projects]]>

I never knew I was an artist until the let me play with lasers ‐Me

Background

A couple of years ago now one of the schools I was working with told me they wanted to start a Maker Space. I didn't realize it but they had brought me into the

]]>
https://iyware.com/my-laser-cutter-projects/5a513274533fe1b5bec542c3Sun, 03 Apr 2016 21:23:24 GMT

I never knew I was an artist until the let me play with lasers ‐Me

Background

A couple of years ago now one of the schools I was working with told me they wanted to start a Maker Space. I didn't realize it but they had brought me into the conversation fairly late.

They had already decided that they were going to buy a laser cutter, in fact they had already purchased it. They wanted to know if I could learn to use it, come up with safety procedures, train some other staff, and help develop classroom application.

Initially I thought "what a terrible idea." In fact, I still kind of do. They spent the entire year's budget for the space on one machine. That's not so practical when it comes to classroom application. I would have much rather bought $10,000 worth of circuit boards, soldering irons, cardboard, fabric, sewing machines, etc... But hey, what was done was done.

At least the machine they ended up getting was really nice. Industrial quality textile-cutting laser with a cutting area of about 3' x 4'. That's enough to make some massive projects.

Over the course of a year I spent a fair amount of time with the machine, learning the ins and outs of how how to use it, developing safety protocols, classroom projects, and maybe (hopefully) exposing myself to some gamma radiation.

Radiation Warning

Seriously though, if you don't close the radiation hood you'll have a pretty good headache after about 15 minutes of operation.

Anyways, I don't consider myself a particularly creative person- and definitely not a visually creative person. I'm terrible with color schemes, bad at UI/UX (which is why I love working with APIs so much), but for some reason I just got totally creative - literally creating things with the laser. Here are some of the projects I created.

Material Templates

I made a bunch of these templates out of different materials, effectively trying to eliminate the guess-work and minimize material waste. Across the top is the material type and laser settings. As well as cut-speed at 10%, 20%, etc... and etch-speed in increments of 5%.

Laser Material Templates

These turned out to be one of the most valuable resources I made.

iPad Case

We even played with etching names onto iPad cases. That was a fun one, and apparently there's big money to be made in this. I'll tell you a secret, it's like 5 minutes worth of work.

Laser Etched iPad Case

Ring Calendar

This calendar was really fun. Again, I don't know where I got the idea, I just kind of came up with it. It's 3 concentric circles, months, dates, and days. I made it for my wife for our anniversary that year. I think she liked it except for the fact that she had to remember to change it every day...

My Calendar

MacBook City Map Case

This one was really fun. I downloaded the XML from the open maps project for Tianjin, converted it to a vector image, cropped it, removed a bunch of stuff except major roads and highways and then flipped it horizontally and etched it on the inside of a MacBook case. The yellow coloring is actually trapped plastic smoke. I'd love to do this one again with a better quality material.

Tianjin Map

Custom Journal

A lot of these projects were simply throwing materials at the laser (or vice versa technically...) and seeing what it could do. I was also playing around with Adobe Illustrator a lot to learn new tricks. I brought a faux-leather journal from home and traced the letter "M" on the cover with a floral pattern inlay and etched my daughter's name on the spine.

Journal Cover

Journal Spine

Basketball

This is where I feel it's important to mention that there are different types of laser cutters. The one we had was for textiles and so moved horizontally on an X and Y axis. It could only handle flat objects. There are other types of lasers which the laser is stationary and 3D objects are moved/rotated under the laser (for etching like mugs, etc...). We tried anyways and put the school's name on a basketball. Notice how the edges are faded as the laser power decreases with distance.

basketball

How thrilled would your IT staff be to get to engrave all the school property with a laser instead of a label maker?!

Christmas Ornaments

I spent a full quarter working with 8th graders teaching them the fundamentals of Adobe Illustrator and vector images. It culminated in a project to create a Christmas ornament which we cut out on the machine. Here's something that's really cool: We used cardboard to prototype, so we were able to do 3 or 4 "drafts" before we cut the final ones out of wood. Here's another thing that's really cool. When kids watch the laser cut out their project and it gets completely demolished you have far more "oh!" moments than you do repeatedly explaining it in a classroom.

Ornaments Cutting

Ornaments Cut

Wooden Ornaments

Coffee Rocket

Even though the laser can only cut vertically, there is a degree of tolerance, it works really well for writing vertically on cylinders. Here's a rocket coffee mug one of the teachers bought for her dad. We etched his name on it.

blast off

Photo Frame

My friend's wife came up with this vision, it's a sort of layered photo frame. The front layer is grass and leaves and the back layer is trunks.

After I gave it to her she painted a landscape behind it, unfortunately I don't have a picture of the finished project, but you get the idea.

photo frame

Chess Board

The crown-jewel of my creations was this chess board. I don't remember how I came up with the idea but I thought that a faux-3D chess board would be so cool. I spent quite a few hours in illustrator laying this out (grr... math.) It's 5 layers of balsa wood with a plexiglass top. I love this thing, in fact it's like the only project I kept.

Check

Checkmate

Conclusion

I love laser cutters. I think that a laser cutter would make a great addition to an already vibrant maker space, but it's not the tool I would pick to start one due to high cost entry, moderate learning curve, and the fact that they're so big it's not feasible to have more than one. That said, they are a wonderful complement to STEAM programs. I would argue that these projects are some of the most artistic, creative things I've done in my life, but they are highly technical and precision engineered (well most of them).

If you're thinking of adding a laser cutter to your arsenal, or already have one, and are trying to figure out some inspirational projects or project-based-learning projects feel free to take any of these ideas listed above. Just be sure to have fun!

]]>
<![CDATA[Utah Pony Express Trail]]>

Today I took my KLR650 on the Pony Express Trail in Utah. It was a fun ride, definitely in the "beginner" category as far as difficulty, but surrounded by lots of great sights none the less.

Pony Express Route

Topographic Pony Express Route

You can see this was about a 350 mile ride and largely

]]>
https://iyware.com/utah-pony-express-trail/5a513274533fe1b5bec542c1Mon, 28 Mar 2016 03:18:51 GMT

Today I took my KLR650 on the Pony Express Trail in Utah. It was a fun ride, definitely in the "beginner" category as far as difficulty, but surrounded by lots of great sights none the less.

Pony Express Route

Topographic Pony Express Route

You can see this was about a 350 mile ride and largely bypassed the mountain passes, which was nice since it was only about 40 degrees when I started out, though the high was 60 degrees later in the day.

KLR in Driveway

Here's the bike at the beginning of the day, ready to go, which was also the point of my first breakdown.

No Fuel

Looks like the fuel line disconnected itself, oops. After that it was a great ride. Here are some photos I took along the way.

]]>
<![CDATA[Add Auxiliary USB Power to a KLR 650]]>

I'd like to start by saying that my long term dream is to rewire my entire bike. Ideally I would move all of the relays and fuses into a weather-tight relay box which is mounted where the starter relay cover is positioned. Then I'd like to add something like the

]]>
https://iyware.com/add-auxiliary-usb-power-to-a-klr-650/5a513274533fe1b5bec542c0Fri, 25 Mar 2016 04:38:57 GMT

I'd like to start by saying that my long term dream is to rewire my entire bike. Ideally I would move all of the relays and fuses into a weather-tight relay box which is mounted where the starter relay cover is positioned. Then I'd like to add something like the Northstar 8000i waterproof USB hub (now discontinued) and mount it where the exhaust fume canister used to be (CA models only). But I'm not there yet, so this is the documentation of simply wiring in a single USB port.

I wrote about swapping in a stainless bolt kit on my KLR650 recently and it really made this work a lot easier. In fact here's all the tools I needed:

Hex and sockets

Well, that's not entirely true- these are the tools needed to take apart the bike. I needed wire strippers/crimpers/cutters for the electrical work and of course I used a torque wrench to put it back together, but the point is my tool roll will be significantly lighter going forward.

The main fuse box is located under the seat.

KLR fuse box

Sadly it only has two fuses, the third is a spare. There's one more in the the starter relay and another someone added with the charger, so adding the USB will make 5 fuses in 3 locations.

Charger fuse

Fortunately the Clymer has a colored wiring diagram which should make this pretty straight-forward. I want to wire this in behind the ignition so it's only on when the key's on. I'm going to wire it behind the 15A fuse because, why not. The alternative is to wire it in front of the fuse, but I think that if I did that a surge might pop both fuses, whereas with the fuse behind the 15A it might save the 7A USB fuse.

KLR wiring diagram

So the plan is to simply use the red power wire and the black-and-yellow for ground.

I already drew out the wiring for when I get a fuse box, and it looks pretty similar to what I'm planning now, so rewiring in the future shouldn't be too complicated.

KR rewire

I already own a weatherproof USB port- which I really like. I've used those crappy 12v cigarette lighters w/ a USB drop-in before and I never liked them. Mostly because it feels like an unnecessary step. Why not just step-down the power directly into a USB port. This one has a nice thick housing and a thick lid with a rotating mount.

USB port

Unfortunately it's currently in pieces because some a-hole stole my battery and in the process just hack-sawed all the wiring. It's two screws you jerk! Anyways... I have to wire it all back together now.

Fuse wires

Here you can see the red power wire coming out of the fuse as mentioned earlier, and the black and yellow ground wire from the battery. Just gotta snip them and wire in the new stuff.

Cut wires

By the way, the manual says to remove the lower fairings to get the gas tank off- but you don't have to. You only have to remove the upper bolt which mounts the fairing to the gas tank.

KLR with no tank and fairings

I used the factory wiring routes instead of zip-tieing everything to the frame.

wired in

And finally attached the fuse and power/ground under the seat and taped everything back together.

Here's the port up by the handlebars and the phone mount.

close up of USB

USB and phone mount

Of course the first time I turned it on, I got nothing. Panicked a little, reviewed the wiring, started to pull the bike apart again, then put another USB cable in and it worked.

]]>
<![CDATA[What's Your Originality Score?]]>

We all know anti-plagiarism software. They take a piece of work and then tell the teacher and the student how original it is. It's a crazy business model. What's even crazier is that schools fork out the cash for it.

So here's the thing, basically these softwares do a search

]]>
https://iyware.com/whats-your-originality-score/5a513274533fe1b5bec542beFri, 04 Mar 2016 03:54:34 GMT

We all know anti-plagiarism software. They take a piece of work and then tell the teacher and the student how original it is. It's a crazy business model. What's even crazier is that schools fork out the cash for it.

So here's the thing, basically these softwares do a search for you and return a certainty-based percentage score that tells you how "original" a student's work is. That's not a very robust feature set for what schools pay for it.

I know the argument is coming about not being able to put a price on academic integrity and blah blah blah, but here's the thing: In higher ed. plagiarism is grounds for immediate failure of the class if not expulsion. When's the last time you expelled a kid, or flunked a kid? Because they're sure as shit plagiarizing. So what are you paying for then? And there's a good counter-point to be made which talks about if it's actually bad to plagiarize or not, but I'm not going there today.

Here's what I want to ask. What's your originality score? You, as a teacher, or even as an individual. If we took the contents of your course and fed them into a search engine that could look across all the internet (including other courses) what percentage would it say is original? Handouts, writing prompts, science experiments, quiz questions, home work, all of it. And don't tell me "but standards" because the point of standards is that you have the freedom to customize the things above as long as they align with the standards.

Put yourself in the shoes of a student as we walk though an imaginary class.

Teacher: Read your textbook (that I didn't write), then download the handout (that I copied off the internet w/o citation) from the course (that an instructional designer made for me). And don't forget that tomorrow we have a quiz (written by a publisher) that includes a reflective essay (which I will assess using canned feedback from the SIS).

Student: ...

Doesn't that reek of hypocrisy? At least a little? Yes, teachers gotta teach. Yes, they're busy because they have 4 preps. Students are busy too; they get this daily from 5 to 9 different teachers.

The point is: Why aren't we leading by example? If it's okay for us to take (hopefully legally!) resources that approximate what we wish to express and rearrange them to suit our purposes, then why can't students? Or, if original expression is so important that saying something unoriginal is grounds for expulsion- shouldn't it also be grounds for termination?

]]>
<![CDATA[Should Students be Content Creators?]]>

In my experience the rhetoric of "we want our students to be content creators not content consumers" is used ad nauseum by faculty and admins for all kinds of purposes. Maybe it's invoked to shut-down a 1:1 initiative or maybe it's just to complain about the youth

]]>
https://iyware.com/should-students-be-content-creators/5a513274533fe1b5bec542bcThu, 03 Mar 2016 02:40:39 GMT

In my experience the rhetoric of "we want our students to be content creators not content consumers" is used ad nauseum by faculty and admins for all kinds of purposes. Maybe it's invoked to shut-down a 1:1 initiative or maybe it's just to complain about the youth.

This argument, I find, is generally indefensible as it ignores the fact that the kids are probably not creating anything now (through no fault of their own- they don't choose curricula) and the adults invoking this ad hominem attack are nothing but content consumers themselves. But the biggest problem I have is that the argument is based on a simple framing error and that is that content creation and content consumption are mutually exclusive.

I propose an alternative idea, and that is consumption and creation are progressive, if not cyclical. Everybody must consume media in order to create it. Ok, must is a generalization but let me make my argument... Is there a director out there, famous or otherwise, who would say, "I have no mentors, no inspiration, my style is my own."? Is there a musician who would say, "I've never heard music before I started making music."? I submit that the answer is "no."

This is not to say that every person who consumes media will necessarily become a de facto content creator, certainly the vast majority of history bears strong evidence to the contrary. Rather, we should be teaching students to move from consumption to creation or to start tipping the scales from 100/0 consumption/creation to 90/10 then 80/20, and so forth. Again, even once someone is renown for their artistic endeavors they hardly stop consuming new inspiration, they just spend the majority of their time creating. Maybe for them the scales have tipped to 80/20 or 90/10 in favor of creation.

So what does this progression look like? Well like all good pedagogy it neatly fits into an easy-to-remember, easier-said-than-done, rule. I call it "The Four 'C's of Creation". They are progressive, but can be cyclical as well.

  • Consume: The person intakes media with no analysis or output
  • Cherish: The person intakes media with internal and/or external analysis and no output
  • Curate: The person intakes media with internal and/or external analysis and derivative output
  • Create: The person intakes media with internal and/or external analysis and original output

Let's take two examples, one generic and one unique to school.

A person listens to music passively on the radio (ha! what's a radio?!). The person discovers a band that they really enjoy learns about the members, the history, the discography, has a favorite song, etc... The person starts creating mix tapes (ha! what's a tape?!) and playlists and sharing them with others. The person starts playing with audio recording creating covers and remixes of the band's songs, sharing them with others. The person starts creating their own unique songs which sounds very similar to the band's songs but over time grow into their own.

In first grade students spend a month reading Dr. Seuss books. In third grade students have to do an oral/written (er... typed) report on your favorite Dr. Seuss book (I won't get into why they have to like Dr. Seuss...). In 6th grade they have to write their own poem a lá Dr. Seuss. In 10th grade they write their own poetry (which can be assigned to the first graders! what?!)

Finally, it should be noted that the creation of good content across all mediums is simply not feasible and the burden of that goal should not be hoisted upon students. Certainly that is an unbearable yoke and we should not be shaming them for simply consuming media. I am not a musical person by any means, and I have never made it past the "cherish" stage listed above. Should I be shamed for this? Should I be guilted into learning an instrument and pretending to have ambitions that simply do not exist? No. I create other things as I consume. I write, I code, I debate (believe it or not, that's an art).

In conclusion I posit that consumption itself is not bad. It's our failure as educators, partially as the result of a framing error, that we do not encourage children to progress from consumption into creation. If we can re-frame our thinking on the purpose of consumption and encourage students to use it as inspiration, then we will see (mildly) transformative change in the realm of artistic creative endeavors in our schools.

]]>
<![CDATA[I Accidentally Bought a 2008 KLR650]]>

Long story short I was planning on moving from China to the USA and needed a bike before I landed so I wired some cash to my father-in-law and started sending him links on craigslist to anything that he would call and low-ball (sorry if you're one of the offended

]]>
https://iyware.com/i-accidentally-bought-a-2008-klr650/5a513274533fe1b5bec542baWed, 24 Feb 2016 05:39:18 GMT

Long story short I was planning on moving from China to the USA and needed a bike before I landed so I wired some cash to my father-in-law and started sending him links on craigslist to anything that he would call and low-ball (sorry if you're one of the offended call recipients). One day he emailed me back and said he had checked out an '09 KLR that looked pretty good, I said "do it."

Beautiful factory "pink" fairings after years in the AZ sun.

I landed in the US and when I came to collect the bike I thought "uh-oh". If it had been me, I wouldn't have bought it: 19,990 miles, laid down on both sides, broken clutch lever, odd idle issues, missing about a half dozen bolts at first inspection, etc... But I smiled, told him "thanks" and took it. It wasn't until I took the title to the DOT to put it in my name (and get my driver's permit as the US doesn't recognize Chinese license) that I realized it said '08. D'oh. I knew I wanted anything but an '08 and here it sits.

I also found the previous owner's "full maintenance log" that was included which when translated from Spanish reads: add oil, add oil, add oil, add water, add oil add oil, add oil...

Oh well this just means I get to do some work. Ordered a doohickey kit from Eagle Mike with the deep hole fix and a 200+ bolt stainless steel kit and shipped them to my brother in California where I'm going tomorrow.

By the way here's my China bike, A Jialing JH150GY-3

Since all the parts are going to California and I'm in AZ I decided to paint the bike, so I jumped in photoshop and started playing around. I have the red '08 but I'm going to repaint the fairings gloss black with Krylon Fusion and clear coat with spraymax 2k enamel. My brother's girlfriend is a graphic designer and she's going to stencil part of the '14 new graphics on for me. This will give me a black and silver looking bike- similar to the black and gray '14. I'm very tempted to take it all the way down to the frame and paint the frame in Kawi green, but I'm a lazy lazy man.

Yeah, I think that's going to look alright. I started pulling the fairings yesterday to prep them for painting, and then I find this:

What the?! A California bike? This is the gift that keeps on giving. Add de-california-ing the bike to the list (I don't live in CA, so calm down).

One final "argh" I have a sweet set of panniers from a company called MotoSevn in China (you can see them up above). They hand make them and hand-make the racks for a ton of bikes. A rack and set of panniers costs about $400 USD. I really wanted to keep my panniers so I brought them with me and before I left I ordered a rack for a KLR from them for about $100 USD. Should look like this:

Except for two problems. First, they sent me the wrong rack.

Second, at some point they switched from 15mm steel tubing to 18mm steel tubing, so I can't even use the 'loops' and get a mount fabricated. Anybody know where I can get a rack with the following dimensions: 31cm x 21cm / 15mm? No? Oh, well.

Got the doo kit + deep hole fix from Eagle Mike, nicely packaged.

and got the stainless steel bolt replacement kit from Desmo Parts, neatly labeled and packaged with thorough instructions:

Started on the valve adjustment and ran into a "huh"? According to the Clymer cam lobes should face away from the engine at TDC, but my lobes are facing toward the engine:

Is this an issue, a misprint, or nothing? Turns out one more crankshaft revolution does the trick (the magic of 4-stroke!). I aligned them 'center' and checked the valves.

OK, all in spec. that will save me some time and money. I'll pop the spark plug out and visually check where the heck TDC actually is But I suspect that it doesn't actually matter for the purpose of checking the valves. Onto the doohickey...

Alternator looks good!

Rotor looks good on the outside

A bit of scoring on the inside, I don't think it's enough to worry about, but it is rough to the touch. Notice the odd scoring pattern on the top-right

Yet again, pristine.

Nice and clean on the inside:

Is it just me or does this NOT look like a stock doo-hickey?

Here it is next to the one from eagle mike:

The main difference is between a machined product vs. a cast product.

Took a couple of days off from work to see my brother and his fiance. Once I got the left crank-case cover off I notice that the inside-seal between the alternator cover and the crankcase cover had a lot of gasket maker gunk stuck to it- so I think it will be necessary to pull the right side cover and check/clean the oil screen, which means I'll need to order a couple of new gaskets. I don't mind since I'm waiting on an oil filter and a small torque wrench from amazon.

In the mean time my spraymax 2k arrived so I can get back to sanding/painting the fairings while I wait for stuff to arrive.

I guess a question is do the new KLRs still have a water pump seal issue? I'm going to order the gaskets anyways so should I order any other parts for the right side? Couldn't resist getting a little more work done...

Those gaskets did not come off very clean

I tried a few things as I was afraid of scoring the aluminum, but I finally ended up using action cleaner/degreaser and some fine steel wool. I figured if it's good enough for cleaning a gun it would probably work for a bike. In order to prevent the steel fuzz from ending up in the alternator case or the balancer guts I held a shop rag inside the case as I worked the steel wool along the rail to prevent anything from falling in.

In the end it turned out pretty good. The wool didn't seem to scratch the surface at all.

When disassembling the bike the whole balancer sprocket fell off because I had the bike on its side stand, so I looked around the garage and found this:

My brother makes Kydex holsters and that's a belt loop template for a spare clip. I propped it under the side stand to get the bike more upright and prevent things from sliding off when trying to reassemble.

When disassembling the bike I kept everything in labelled baggies, here's the balancer and the old doohickey.

Well that went back together as easily as it came apart.

Now it's time to start reassembling the casings. First I applied some dressing to the faces with a Q-Tip using this:

Now I can start reinstalling using the stainless kit.

Here's a stock bolt compared to a new stainless:

Unfortunately the kit didn't include the one hidden bolt that lives inside the casing (the one that's shorter than the others)

Applied some copper-based anti-seize lubricant to the end of the threads and started installing.

On to the doohickey.

I reinstalled the washer and the bolt and tightened slightly to prevent it from slipping while trying to hook the torsion spring.

I ended up using two pairs of needle-nosed pliers, the first I grabbed at the base of the 'U' and pulled across, the second I grabbed the end and used to insert into the doohickey hole.

It seems like the spring might want to fall 'forward' off of the face of the doohickey, especially since it's a graded surface, should I be concerned about that?

I'm stopping on reassembly there since I don't have a torque wrench that goes as low as needed, so I will wait for it to arrive

Of course I couldn't have gotten any work done without help from the boy.

So there she sits for now, occupying the primo space in the garage. As you can see we're not brand loyalists (not pictured the 2 hondas and the yamaha)

Water pump gasket and clutch cover gasket arrived from Partzilla yesterday, just waiting for that torque wrench from Amazon which should be here today.

They really outdid themselves on the packaging for this one

Pulled the rotor and starter clutch gears back out, as well as the new (massive) tube of moly-infused grease

Loaded it up in the grease gun and put a dab on the woodruff key to help keep it in place, as the key slot was currently sitting at about 3 o'clock- as an aside loading the grease gun was a pain as it's about a 2" diameter and the canister was 2 1/2" diameter...

Put a little dab at the end of the spacer for the deep hole fix as well- just to keep it seated during installation.

Reading the descriptions of what the issue was and what it now fixes finally make sense, I guess a picture is worth a thousand words

New rotor bolt ready to go.

I couldn't find a deep 19mm socket and with the rotor tool installed the torque wrench wouldn't seat properly so I had to find an extension- this left me plenty of room but I was afraid of creating a bit of a moment arm and messing up the torque ratings, but I think it went alright.

ran out of long zip ties...

Starter clutch gears reinstalled. There's really only one way to install these so it's hard to get wrong, just make sure that all the teeth are seated between all the gears. It might be possible to have a starter clutch gear not installed all the way and close up the case. Unfortunately the clymer only provides all photos directly from in front so it's kind of hard to see the proper installation, so here's a clarifying photo.

More gasket prep, new gasket, and new stainless bolts with anti-sieze on the threads. Now it's starting to look like a functioning motorcycle, and best part is I don't have any extra screws or washers left over (My grandpa always ended up with extra screws and washers )

Those stainless bolts look kinda beefy if I do say so myself. Still have a lot of cleaning left to do on this side, then I tear down the right side and move back up to the top end. Maybe some day I'll ride this thing...

The front sprocket and sprocket guard area were much dirtier than I thought. There was a track for the chain through the gunk. Liberal amounts of wd40, a flathead screw driver and a few shop rags took care of it.

It wasn't officially in the stainless kits but they provided a ton of extra bolts so I swapped out the shifter bolt while I was at it (this is a spare oil filter cover bolt). Cleaned the crap off the shifter lever while I was at it

Swapped out the oil filter - the previous one was manufactured 5 years ago, so it's probably due. It didn't seat very well either on the outside or around the shaft, but this could also just be due to age, heat, and pressure.

Drained the coolant and promptly spilled it all over the garage floor so I decided to call it a day.

Started in on the right side of the bike- boy that's a lot of corrosion on those bolts.

And some rust. Good thing they'll be replaced with stainless.

Got the oil screen out and there was some gasket maker which I expected but there was also some black plastic and a couple of shards of aluminum inside the crankcase where the oil screen sits.

Also found a pea-size glob of oil that had forced its way out of the case near the brake pedal mount- guess It's a good thing I'm replacing the gasket anyways...

Put it all back together giving it the stainless treatment and added some 20W-50 oil and 50/50 coolant, now back up to the topend and it'll actually be ready to ride.

Everything looked good so it was time to put the top end back together too. Pulled the old silicon (and gasket maker) off

Added new silicon sealant

threw in a new spark plug and put the bike together enough to start it. Fired up the first time and turned it off after 30 seconds, checked the coolant and it looked good.

Turned it back on and let it idle, while adjusting the idle to ~1200 RPM. While adjusting the idle I noticed a small puff of black/gray smoke from the rear-end of the right-side of the engine block. I cursed and turned the bike off, wiped down the whole thing and turned it back on. No more smoke, hopefully it was just a little bit of residue.

I did have a single drop of coolant fall from here (the open hole between the coolant drain plug and the engine housing bolt):

I'm going to assume that's OK since it was just a single drop. So here she runs:

Now I just need to finish painting... and put on the stainless bolt frame kit.. and do the other maintenance... and... and... ahh I'll just go ride.

I forgot to say, this bike was manufactured in April 2007 in Thailand. Seems to be one of the first, the last 5 of the VIN is 02### - so it seems pretty early.

Finished wet sanding everything with a 400 grit sand paper today. I was able to use the power sander only on the black fairings, everything else was done by hand. The power sander did a good job pulling the gloss finish off, but I still had to get some of it by hand.

My wife said it looks like the batmobile now. Kinda hard to tell here but this is a small dog kennel with rope run across and clothes hangars- nice and professional.

For this type of stuff I'm going to skip the clear enamel, we'll save that for the fenders, and fairings. Here's the "before" for the rear rack. It was this faded before I sanded it.

And here's the after.

The paint looks unevenly colored but that's just a combination of light and texture- it came out really well. This is just krylon fusion gloss black. I did a grip coat, a "primer" coat, and then three thick coats waiting 15 minutes between each coat.

I also wasn't going to paint the radiator cover or overflow cover, but since I had them off I figured "why not?" It allowed me to do a good test on some semi-hidden parts.

You might see some white flecks on some of the pieces- that's salt from the Bug-A-Salt rifle- but it's just sitting on dry paint, it's not in the paint.

Tomorrow I'll hit the rest of the non-essential parts including the sprocket cover, master cylinder guard, rear fender/license plate holder, and city light cover. Then I'll move on to the big stuff that will get probably one or two more coats and two or three coats of enamel.

Since it's getting above 90 in the afternoons I can only paint in the morning, so afternoons will be spend de-california-ing the bike as well as swapping out the frame bolts for stainless.

Marked off the "important" stuff and kept painting. Grip, primer x2, and 4 top coats.

Got a little lazy when it came to the tank- just sanded a surface on it taped it off and painted it. I also dropped the tribal/flame pattern for a solid space.

I was waiting for my brother's girlfriend to be able to do some graphics but she's busy and I found a 2015 new graphics kit on ebay for $50 so I ordered that. Once it arrives I'll apply it to the bare paint and then apply top coat. That will prevent the graphics from peeling.

Now it's the waiting game again...

Forgot to do this before I painted so I grabbed the dremel and cut the broken part of the tail off below the license plate mount. Put a round corner on it and painted it.

While I'm waiting for the decal set to arrive I decided to swap out the stock bolts for the stainless set. This means I'll be doing some of them twice when I reinstall the parts I painted, but whatever- it's one more thing I can do now.

before and after (not torqued)

It's probably a good thing I ordered this kit anyways since I'd want to replace some of these eventually.

Scotch-taping a well-nut, that's a new one for me... Of course another one was glued in

I have to say that one thing that surprised me with this bolt kit was how generous they were. If it called for 11 bolts they provided 16. Where you needed nylon washers they provided both black and opaque.

I thought the bolts for the bar ends were torqued down incredibly tight, that was until I finally broke them and got them out...

This bolt kit had something like 140+ stainless bolts and they probably gave me 200+ bolts. The problem is that the bike could easily swap probably 160 bolts, so now that I'm done with the instructions for the kit I'm chasing down extra screws on the bike and seeing if I have a stainless that can replace it, like these:

By the way, are the soft luggage racks not a stock option on the bike? The stainless screws that were in the kit were far too short for me to put these back on. It's not important to me since I'm getting a proper luggage rack at some point, just curious.

This bolt (dead center), by the ways, is the most infuriating bolt I've found on the bike. it's dead simple to get it out on the right-hand side but it took forever to get this one out, and I still haven't been able to get it started again, there's just not enough room for a socket wrench

To get that bolt re-set I ended up taking off the whole upper fairing, which allowed me to replace quite a few bolts with stainless. All of the following are bolts that are NOT includes in the desmos instructions, but that I was able to replace with spare parts included with the kit.

Upper fairing (inside)

Upper fairing (outer)

Pillion foot peg mounts

Air box filter mount and electric cable guide mount

Rear fender connectors

Radiator fan mounts

Brake pedal

Kick stand electrical cover

Exhaust heat shield

The exhaust heat shield bolts are the only ones I had to modify- I cut them down to about half length using the dremel. I also had to get some of my own crush washers, other than that all of the above came from the bolt kit.

Pulled all of the CA exhaust crap- that's an out of control amount of stuff.

I rerouted the tank vent tube under seat

I also pulled the battery vent tube drain since this battery doesn't seem to have a drain.

This allowed me to re-route the air box drain tube through the fairing where the battery drain tube used to be.

And what on earth is this tube? I chased it up under the gas tank- but I didn't want to pull the tank to find out what it is. This seems ridiculously long. A cursory glance through the manual didn't show what it is.

I have a few more minor bolts that I'll try to replace tomorrow, like cable guide mounts etc..., and I think I'll be done with the stainless kit.

Turns out that stupid long hose is the radiator tank overflow line, knowing that I was able to re-route it directly into the overflow tank mount, removing about 3' of hose. Now it will just dump directly out the front of the bike.

Finished up the stainless bolt swap by grinding down a few remaining bolts and replacing the radiator overflow tank housing frame mounts and some cable guide mounts.

While I was swapping bolts I removed this- it looks like it was supposed to be holding/guiding something but it was not- it was just sitting there (see the empty hole in the middle of the photo above, so for now I've removed it. Unless it's necessary I'll just keep it off for now.

I also threw in a new cotter pin on the rear wheel- notice how beat up that old thing is. Now it's back to waiting for my decals to arrive.

Turns out waiting IS the hardest part. FedEx said my decals made it to town on Saturday morning but wouldn't be delivered until Thursday- but I could request to pick it up at the facility. I requested to hold for pickup and made the 30 minute drive to the airport, only to be told that it was there but not sorted yet- I can come back by maybe Tuesday or Wednesday to pick it up.

Also got a package in the mail from China with my old handguards. Tried them out and they don't fit the KLR they sit too low, bummer- but I guess it gives me one less thing to paint...

So I stuck them on the TT-R instead.

I completely forgot about my tailbox amongst all the other things. I have a nice large BJG brand aluminum box that a friend gave me and I wanted to try to make it quick release like my panniers. It was already drilled but I can't reuse those holes and make it quick release so, note to self- this box isn't water proof!

I bought a 4 eye-bolts and some wingnuts and cap nuts which won't work together... The goal is to eventually swap the wingnuts for a threaded washer with a cap nut.

The idea is to mount the eye bolts and allow them to rotate on and off the mounting plate to quickly release.

Used the Dremel to open up the eye bolts for them to mount to the rear plate.

Then I decided to add a vacuum cap to the end of the bolt for a little more grip.

Now it's mounted, sturdy, and not moving anywhere.

I noticed that mounting the tail box scuffed up my new paint job on the rear rack- and we can't have that yet so I went to harbor freight and bought a roll of tool box drawer liner, simple rubber matting that's about 2mm thick and used silicon RTV to attach it to the bottom of the box. I then decided I might as well line the inside of the box as well.

The corners didn't come out so well inside of the box, oh well...

I figure between rubber on the eye bolts and rubber on the bottom of the box I should get a better mount with less slip

My package was finally available for pickup from Fedex, I left off about 1/2 of the kit- I wanted something minimal. Also cut off all the gray stripe accents from what I did apply, except for the 650 part.

I'll clearcoat on Wednesday and then hit the pavement.

Oh yeah, the stickers came from Venezuela (what copyright?!) from a company called backup kits. They also make some cool wraps and some that have, uh... character.

Got it all put back together after clear coating, here she sits.

Now for the fun project!

I took an old gardening mat, wrapped it in Gorilla tape, glued it to some poplar board that I sprayed black and attached both some industrial Velcro and some fabricated Kydex clips and voila! a backrest for the pillion

Since the bottom is velco, it doesn't have to be removed to open the tail box

This was supposed to be a prototype but it does its job. When it breaks I'll do a version 2. Now I need to start thinking about luggage racks again...

After I moved to Utah I added new tires, a new battery, and new chain. There's still lots more I want to do, just need time and money, but I'm having too much fun riding to!

]]>
<![CDATA[Gridster for Instagram]]>

Gridster for instagram v1.0

Gridster for instagram is the easiest way to get a customized, full-screen, display of any instagram feed. As its name implies, Gridster loads the images you want into a photo wall and animates through them.

Installation

Navigate to the assets/js folder open the Gridster.

]]>
https://iyware.com/gridster-for-instagram/5a513274533fe1b5bec542b5Sat, 17 Oct 2015 22:09:53 GMT

Gridster for instagram v1.0

Gridster for instagram is the easiest way to get a customized, full-screen, display of any instagram feed. As its name implies, Gridster loads the images you want into a photo wall and animates through them.

Installation

Navigate to the assets/js folder open the Gridster.js file and enter your clientID on line 1.

Usage

Simply open in your browser and Gridster will display the most popular images on instagram. Click on the hashtag to enter full-screen mode.

Customization

There are two ways to customize the output of Gridster, the first is with the URL query string and the second is by editing Gridster.js

Query String

There are a number of options that you can use to customize the display of Gridster using the query string.

  • tag: You can use tag=tagname to show a specific tag from instagram. If no tag is provided, images from the "popular page" are displayed. You don't need to add "#" at the beginning, just the name of the tag. [default: null]
  • images: You can use images=## to set how many images to fetch (maximum 60). [default: 60]
  • speed: You can use speed=## to control the speed in seconds of the animation transitions between images. [default: 1]
  • pause: You can use pause=## to control the time in seconds the scroll pauses between animations. [default: 10]
  • reload: You can use reload=## to control the time in minutes Gridster waits to get new images from instagram. [default: 60]
  • sort: You can use sort=none to control the order in which the images are sorted on the page. Available sort options are: none, most-recent, least-recent, most-liked, least-liked, most-commented, least-commented, and random. [default: none]
  • animation: You can use animation=scale to control the animation type used to transition between images. Available animation options are: showhide, fadeinout, slideleft, slideright, slidetop, slidebottom, rotateleft, rotateright, rotatetop, rotatebottom, scale, rotate3d, rotateleftscale, rotaterightscale, rotatetopscale, rotatebottomscale, and random. [default: random]
  • rows: You can use rows=## to specify the number of rows in the grid. [default: 3]
  • columns: You can use columns=## to specify the number of columns in the grid. If the total images in rows multiplied by columns is more than specified in "images" then Gridster will subtract columns until the grid is full. [default: 4]
  • step: You can use step=## or step=random to control the number of animations that occur simultaneously. [default: random]
  • maxstep: If step is set to "random" you can set maxstep=## to control the maximum amount of animations that occur at once. [default: 2]
  • author: You can use author to display the username of the person who posted the picture. [default: null]
  • caption: You can use caption to display the caption that was originally posted with the image (including hashtags) [default: null]
  • comments: You can use comments to display the comment count on the image. [default: null]
  • likes: You can use likes to display the number of likes on an image. [default: null]
  • link: You can use link so that clicking the image will take the user to the image post on instagram. [default: null]
  • background: You can use background=red to change the default background color. If you use hex or rgb be sure to encode the URL. [default: null]
  • color: You can use color=purple to change the default font color. If you use hex or rgb be sure to encode the URL (# is %23). [default: null]
  • clientid: You can use clientid=## to provide or override a clientID inserted in Gridster.js. [default: null]

Gridster.js

Most of the variables that control the output of Gridster are in the urlParams{} object. Simply change the default values that you want. If you don't want users to be able to modify the output with the query string then at the top of Gridster.js set enableQuery = false; and only the settings from the js file will be used.

Examples

?tag=spring&author&sort=random: Display 60 large images all tagged "spring" with the username displayed, randomly displaying them in the grid.

?sort=most-liked&speed=0&refresh=5&likes&link: Display a small grid that doesn't animate of the most popular images on instagram that refreshes every 5 minutes, sorted by likes and you can click to see the original on instagram.

?tag=tbt&author&likes&comments&caption: See who's throwing back and what they have to say about it.

License

Gridster is built using a combination of open source and proprietary code. The individual licenses for each open source component can be found in the LICENSE folder.

Main

Gridster for instagram is copyright 2015 Danny Wahl, all rights reserved except where specified in the LICENSE file.

Vendor

Changelog

  • 1.1
    • Content reload doesn't exit fullscreen anymore
    • readme now written in html
  • 1.0
    • Initial release

Download Gridster for Instagram

]]>
<![CDATA[My Posts WordPress Plugin]]>

My Posts

If you run a multi-author blog you've probably noticed that it's not so easy to find only your posts. "My Posts" fixes that by adding a link under the "Posts" menu that goes directly to a list of posts written by the current user.

My Posts

]]>
https://iyware.com/my-posts-wordpress-plugin/5a513274533fe1b5bec542b7Fri, 29 May 2015 04:01:51 GMT

My Posts

If you run a multi-author blog you've probably noticed that it's not so easy to find only your posts. "My Posts" fixes that by adding a link under the "Posts" menu that goes directly to a list of posts written by the current user.

My Posts is compatible with WordPress 3.0 and up and works with WPMU and Adminimize. What are you waiting for? Download it now from the WordPress plugins database.

Download My Posts for WordPress

]]>
<![CDATA[Scrollster for Instagram]]>

# Scrollster for instagram logo

Scrollster for instagram is the best way to showcase instagram photos in a beautiful, full-screen, responsive scrolling gallery. Scrollster for instagram is a standalone webapp you can run it from your desktop or from a server.

Scrollster for instagram is very customizable: You choose what images to display, how many,

]]>
https://iyware.com/scrollster-for-instagram/5a513274533fe1b5bec542b3Tue, 21 Apr 2015 00:30:02 GMT

# Scrollster for instagram logo

Scrollster for instagram is the best way to showcase instagram photos in a beautiful, full-screen, responsive scrolling gallery. Scrollster for instagram is a standalone webapp you can run it from your desktop or from a server.

Scrollster for instagram is very customizable: You choose what images to display, how many, how large, comments, likes, you name it! And customization is a snap.

Download Scrollster for Instagram


Installation

Navigate to the assets/js folder open the scrollster.js file and enter your clientID on line 1.

Usage

Simply open in your browser and Scrollster will display the most popular images on instagram. Click on the hashtag to enter full-screen mode.

Customization

There are two ways to customize the output of Scrollster, the first is with the URL query string and the second is by editing scrollster.js

Query String

There are a number of options that you can use to customize the display of Scrollster using the query string.

  • tag: You can use tag=tagname to show a specific tag from instagram. If no tag is provided, images from the "popular page" are displayed. You don't need to add "#" at the beginning, just the name of the tag. [default: null]
  • images: You can use images=## to set how many images to fetch (maximum 60). [default: 60]
  • size: You can use size=small to select which size image to fetch from instagram. Available sizes are: small, medium, and large. [default: large]
  • speed: you can use speed=## to control the speed in seconds the page takes to scroll from top to bottom and vice versa. [default: 90]
  • pause: You can use pause=## to control the time in seconds the scroll pauses at the top and bottom of the screen. [default: 10]
  • reload: You can use reload=## to control the time in minutes Scrollster waits to get new images from instagram. [default 60]
  • sort: You can use sort=none to control the order in which the images are sorted on the page. Available sort options are: none, most-recent, least-recent, most-liked, least-liked, most-commented, least-commented, and random. [default: none]
  • author: You can use author to display the username of the person who posted the picture. [default: null]
  • caption: You can use caption to display the caption that was originally posted with the image (including hashtags) [default: null]
  • comments: You can use comments to display the comment count on the image. [default: null]
  • likes: You can use likes to display the number of likes on an image. [default: null]
  • link: You can use link so that clicking the image will take the user to the image post on instagram. [default: null]
  • background: You can use background=red to change the default background color. If you use hex or rgb be sure to encode the URL. [default: null]
  • color: You can use color=purple to change the default font color. If you use hex or rgb be sure to encode the URL (# is %23). [default: null]
  • clientid: You can use clientid=## to provide or override a clientID inserted in scrollster.js. [default: null]

scrollster.js

Most of the variables that control the output of Scrollster are in the urlParams{} object. Simply change the default values that you want. If you don't want users to be able to modify the output with the query string then at the top of scrollster.js set enableQuery = false; and only the settings from the js file will be used.

Examples

?tag=spring&author&sort=random: Display 60 large images all tagged "spring" with the username displayed, slowly scrolling up and down.

?size=small&sort=most-liked&speed=0&refresh=5&likes&link: Display a small grid that doesn't scroll of the most popular images on instagram that refreshes every 5 minutes, sorted by likes and you can click to see the original on instagram.

?tag=tbt&author&likes&comments&caption: See who's throwing back and what they have to say about it.

License

Scrollster is built using a combination of open source and proprietary code. The individual licenses for each open source component can be found in the LICENSE folder.

Main

Scrollster for instagram is copyright 2015 Danny Wahl, all rights reserved except where specified in the LICENSE file.

Vendor

Changelog

  • 1.2
    • Minimized logo
    • Removed extra CSS selectors
  • 1.1
    • Fix scroll/pause timing: Now runs as soon as the page is loaded
    • Fix reference to scroll.js to scrollster.js
  • 1.0
    • Initial release

Download Scrollster for Instagram

]]>
<![CDATA[Add Share Links to WordPress]]>

In my previous posts Ghost Share Links Cheat Sheet and Add Share Links to Ghost Themes I explained "no-cost" sharing and provided reusable code snippets in handlebars to add share links to 19 different social networks. Here they are adapted for WordPress in a single easy to use

]]>
https://iyware.com/add-share-links-to-wordpress/5a513274533fe1b5bec542b1Wed, 25 Mar 2015 00:19:11 GMT

In my previous posts Ghost Share Links Cheat Sheet and Add Share Links to Ghost Themes I explained "no-cost" sharing and provided reusable code snippets in handlebars to add share links to 19 different social networks. Here they are adapted for WordPress in a single easy to use function.

tl;dr: Download WordPress shareLinks at github.

Installing

In your WordPress theme folder you can either simply add the following code to the single.php file inside of the while() loop or add it to your theme's functions.php and call it in single.php

Usage

This code provides a single function shareLinks([$sites]){} which takes an optional parameter $sites[] which is array of sites to output links. If no parameter is provided then all sites are returned. For example:

shareLinks();  //All the things!

shareLinks(array("email")); //Old School!

ShareLinks(array("sinaWeibo", "renren")); //你好!

The function returns a string containing an unordered list with each site as its own list item. The list item contains an anchor with a helper class of the machine-readable site name, like so:

<ul>
  <li>
    <a class="stumbleupon" href="https://stumbleupon.com...">StumbleUpon</a>
  </li>
  <li>
    ...
  </li>
</ul>

To output the list it needs to be echoed after it is called. The simplest way is like this:

<?php echo shareLinks(); ?>

Ok, now for the dev-nerd stuff...

Query Items

Different networks require/allow different query items and as such shareLinks() provides a number operators:

  • $share["siteTitle"]: This is a string returned from get_bloginfo('name').

  • $share["siteURL"]: This is a string returned from get_site_url().

  • $share["postTitle"]: This is a string returned from get_the_title().

  • $share["postURL"]: This is a string returned from get_permalink() and then passed through remove_query_arg() to remove the page indicator. If you want to share a specific page of a post then you'll need to remove the remove_query_arg() call.

  • $share["postCategory"]: This is a string of all categories of the post returned from get_the_category() and then the spaces are stripped out of category names and each category is prefixed with "#". For example if a post is categorized as "Word Press, Themes" the return would be " #WordPress #Themes".

  • $share["postDblCategory"]: This is the same as $share["postCategory"] except categories are also suffixed with "#" as is required by some networks. For example if a post is categorized as "The Simpsons, Ralph Wiggum" the return would be "#TheSimpsons# #RalphWiggum#".

  • $share["postExcerpt"]: This is a string returned from get_the_excerpt() and then passed to wp_strip_all_tags(): This will have "Continue Reading" at the end. If you want to remove that you'll need to add a filter to your theme.

  • $share["postShortExcerpt"]: This is $share["postExcerpt"]: substringed to the first 90 characters for networks with shorter share limits.

  • $share["postImage"] This is the URL of the featured image of the post. If there is no featured image for the post, then it will grab the URL of the first image attached to the post. If there are no images in the post then it is empty- which is fine.

Networks Array

Each network (facebook, twitter, etc..) is simply part of a multidimensional array. To add another network, simply create another entry in networks[]. Here's the schema of the primary array:

	$networks["network-machine-readable-name"] = [
		"name"  => "Network Display Name",
		"url"   => "https://example.com/share?",
		"query" => [
		    "foo" => $share["postURL"]
            "bar" => $share["postTitle"],
		],
	];

The machine readable name is the helper class that's provided in the anchor, the "name" is the text output in the anchor content. This is important especially when dealing with multilingual sites, for example "Sina Weibo" is $networks["sinaWeibo"] but the display name is: "name" => "新浪微博" to change the display of the network name you would change the "name" value.

The "url" array value is where the share URL is stored- this is different for each site, but it should always end with the beginning of the query URL (i.e. ?).

The "query" array value should store another array which are the components of the URL query. These are different for each network, but can be populated with elements from the $share[] array as outlined above. For example a query array might look like this:

"query" => [
    "url" => $share["postURL"],
    "title" => $share["postTitle"],
    "redirect" => "false",
],

Notice the last option "redirect=false". It's possible to add static elements to the query URL if they're required by the remote site. In the end this will give us something like:

url=http://example.com&title=Post Title&redirect=false

Finally, our query is passed through http_build_query() to make it URL encoded.

Examples

The following are real examples of this function in action on my wife's blog (iywahl.com) with a random post. Her site is using WordPress 4.1.1 and the "Twenty Fifteen" theme.

Email

	$networks["email"] = [
		"name"  => "E-mail",
		"url"   => "mailto:?",
		"query" => [
		    "subject" => $share["siteTitle"] . ": " . $share["postTitle"],
			"body"    => $share["postTitle"] . "\r\n" . $share["postURL"] . "\r\n\r\n" . $share["postExcerpt"],
		],
	];

twitter

	$networks["twitter"] = [
		"name"  => "twitter",
		"url"   => "https://twitter.com/home?",
		"query" => [
		    "status" => $share["postURL"] . $share["postCategory"],
		],
	];

Facebook

	$networks["facebook"] = [
		"name"  => "Facebook",
		"url"   => "https://www.facebook.com/sharer/sharer.php?",
		"query" => [
			"u" => $share["postURL"],
		],
	];

Google+

	$networks["googlePlus"] = [
		"name"  => "Google+",
		"url"   => "https://plus.google.com/share?",
		"query" => [
			"url" => $share["postURL"],
		],
	];

LinkedIn

	$networks["linkedin"] = [
		"name"  => "LinkedIn",
		"url"   => "https://www.linkedin.com/shareArticle?",
		"query" => [
			"mini"    => "true",
			"url"     => $share["postURL"],
			"title"   => $share["postTitle"],
			"summary" => $share["postExcerpt"],
			"source"  => $share["siteTitle"],
		],
	];

Pinterest

	$networks["pinterest"] = [
		"name"  => "Pinterest",
		"url"   => "https://pinterest.com/pin/create/button/?",
		"query" => [
			"url"         => $share["postURL"],
			"media"       => $share["postImage"],
			"description" => $share["postShortExcerpt"], 
		],
	];

Tumblr

	$networks["tumblr"] = [
		"name"  => "tumblr",
		"url"   => "http://www.tumblr.com/share/link?",
		"query" => [
			"url"         => $share["postURL"],
			"name"        => $share["postTitle"],
			"description" => $share["postExcerpt"],
		],
	];

reddit

	$networks["reddit"] = [
		"name"  => "reddit",
		"url"   => "http://www.reddit.com/submit/?",
		"query" => [
			"url"   => $share["postURL"],
			"title" => $share["postTitle"],
		],
	];

Xing

	$networks["xing"] = [
		"name"  => "Xing",
		"url"   => "https://www.xing.com/spi/shares/new?",
		"query" => [
			"sc_p" => "xing-share",
			"url"  => $share["postURL"],
		],
	];

VK

	$networks["vk"] = [
		"name"  => "VK",
		"url"   => "https://vk.com/share.php?",
		"query" => [
			"url"         => $share["postURL"],
			"title"       => $share["postTitle"],
			"description" => $share["postExcerpt"],
			"image"       => $share["postImage"],
			"noparse"     => "true",
		],
	];

buffer

	$networks["buffer"] = [
		"name"  => "buffer",
		"url"   => "https://bufferapp.com/add/?",
		"query" => [
			"url"  => $share["postURL"],
			"text" => $share["postShortExcerpt"],
		],
	];

StumbleUpon

	$networks["stumbleupon"] = [
		"name"  => "StumbleUpon",
		"url"   => "https://www.stumbleupon.com/submit?",
		"query" => [
			"url"   => $share["postURL"],
			"title" => $share["postTitle"],
		],
	];

新浪微博 (Sina Weibo)

	$networks["sinaWeibo"] = [
		"name"  => "新浪微博",
		"url"   => "http://service.weibo.com/share/share.php?",
		"query" => [
			"url"   => $share["postURL"],
			"pic"   => $share["postImage"],
			"title" => $share["postTitle"] . "%0D%0A" . $share["postShortExcerpt"] . $share["postDblCategory"],
		],
	];

Baidu空间

	$networks["baidu"] = [
		"name"  => "Baidu空间",
		"url"   => "http://hi.baidu.com/pub/show/share?",
		"query" => [
			"url"   => $share["postURL"],
			"title" => $share["postTitle"],
		],
	];

人人网 (Renren)

	$networks["renren"] = [
		"name"  => "人人网",
		"url"   => "http://share.renren.com/share/buttonshare?",
		"query" => [
			"link"  => $share["postURL"],
			"title" => $share["postTitle"],
		],
	];

腾讯微博 (QQ Tencent Weibo)

	$networks["tencentWeibo"] = [
		"name"  => "腾讯微博",
		"url"   => "http://v.t.qq.com/share/share.php?",
		"query" => [
			"title" => $share["postTitle"] . " " . $share["postShortExcerpt"] . $share["postDblCategory"],
			"url"   => $share["postURL"],
		],
	];

QQ空间

	$networks["qzone"] = [
		"name"  => "QQ空间",
		"url"   => "http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?",
		"query" => [
			"title"   => $share["postTitle"],
			"url"     => $share["postURL"],
			"summary" => $share["postShortExcerpt"],
		],
	];

腾讯朋友网 (Pengyou)

	$networks["pengyou"] = [
		"name"  => "腾讯朋友网",
		"url"   => "http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?",
		"query" => [
			"to" => "pengyou",
			"title"   => $share["postTitle"],
			"url"     => $share["postURL"],
			"summary" => $share["postShortExcerpt"],
		],
	];

Wow, are you still reading this? Go download shareLinks from github and add it to your theme!

]]>
<![CDATA[Ghost Theme Lenore]]>

Ghost is a blogging platform. Lenore is a theme designed to showcase writing and as such most of its features are about what it doesn't do.

Demo

A demo site of this theme is available at lenore.iyware.com

Features

]]>
https://iyware.com/ghost-theme-lenore/5a513274533fe1b5bec542aeThu, 19 Mar 2015 04:50:20 GMT

Ghost is a blogging platform. Lenore is a theme designed to showcase writing and as such most of its features are about what it doesn't do.

Demo

A demo site of this theme is available at lenore.iyware.com

Features

Un-features

  • Exactly one layout. Use it with or without images, logos, descriptions, bios; it looks great with any options- and you don't have to edit a thing, it just works.
  • No grid
  • No JavaScript
  • No images
  • No external resources!
  • No shims, fallbacks, or browser hacks ‐ because you don't need them

Browser Compatiblity

✓Firefox 
✓Safari 
✓Chrome 
✓IE9

✓iOS Safari 7 
✓Opera 
✓Android 
✓Vivaldi

Layouts

Lenore supports several different content configurations, below are links to some examples. Note that none of these examples require theme customization, they just work.

Author

Author archive: ✓image, ✓cover

Author archive: ✗image, ✗cover

Author post: ✓with bio

Author post: ✗bio

Page

Page: ✓image

Page: ✗image

Tag Archive

Tag archive: ✓image, ✓description

Tag archive: ✗image, ✓description

Tag archive: ✓image, ✗description

Tag archive: ✗image, ✗description

Post

Post: ✓image

Post: ✗image

Post: ✓tags

Post: ✗tags

Customization

Lenore is easy to customize and everything you want to customize is commented in the file you need to edit.

Stylesheets

The CSS has a table of contents and comments labeled inline. Want to change the link color? Find it in the table of contents and search for it. It's this easy:

a {
	color: #4b87aa; /*<==11*/
	text-decoration: none;
	transition: all 0.25s;
}
a:hover,
a:focus,
a:active{
	color: #068bd8; /*<==12*/
}

Or how about the max-width of post content?

    article {
	    max-width: 34rem; /*<==06*/
    }

Social Sharing

There are also a number of social sharing links in post.hbs. By default only 5 are enabled. To enable or disable different networks, simply uncomment them by removing the handlebars around the <li> elements:

{{!--REDDIT
	<li><a class="reddit" href="http://www.reddit.com/submit/?url={{@blog.url}}{{url}}">reddit</a></li>
--}}

becomes:

    <li><a class="reddit" href="http://www.reddit.com/submit/?url={{@blog.url}}{{url}}">reddit</a></li>

All social networks have a helper class for ease of styling. In total there are 19 sharing options provided.

Download & Support

Lenore is available for download on github and support is provided via github issues.

Download Lenore: A Theme for Writing

]]>
<![CDATA[Ghost Share Links Cheat Sheet]]>

In my previous post Add Share Links to Ghost Themes I outlined how to create no-cost share links using the Ghost handlebars API. In this post I'll provide code snippets to some of the most popular social networks that you can simply copy and paste into your custom theme.

Email

]]>
https://iyware.com/ghost-share-links-cheat-sheet/5a513274533fe1b5bec542acMon, 16 Mar 2015 12:20:12 GMT

In my previous post Add Share Links to Ghost Themes I outlined how to create no-cost share links using the Ghost handlebars API. In this post I'll provide code snippets to some of the most popular social networks that you can simply copy and paste into your custom theme.

Email

<a href="mailto:?&subject={{encode @blog.title}}%3A%20{{encode title}}&body={{encode title}}%0D%0A{{url absolute="true"}}%0D%0A%0D%0A{{excerpt words="45"}}%2E%2E%2E">
    Email
</a>

twitter

<a href="https://twitter.com/home?status={{url absolute="true"}}%20{{tags prefix="%23" separator="%20%23" autolink="false"}}">
    Twitter
</a>

Facebook

<a href="https://www.facebook.com/sharer/sharer.php?u={{url absolute="true"}}">
    Facebook
</a>

Google+

<a href="https://plus.google.com/share?url={{url absolute="true"}}">
    Google+
</a>

LinkedIn

<a href="https://www.linkedin.com/shareArticle?mini=true&url={{url absolute="true"}}&title={{encode title}}&summary={{excerpt words="45"}}&source={{@blog.title}}">
    LinkedIn
</a>

Pinterest

<a href="https://pinterest.com/pin/create/button/?{{url absolute="true"}}{{#if image}}&media={{@blog.url}}{{image}}{{/if}}&description={{excerpt words="20"}}">
    Pinterest
</a>

tumblr

<a href="http://www.tumblr.com/share/link?url={{url absolute="true"}}&name={{encode title}}&description={{excerpt words="45"}}">
    Tumblr
</a>

reddit

<a href="http://www.reddit.com/submit/?url={{url absolute="true"}}&title={{encode title}}">
    reddit
</a>

Xing

<a href="https://www.xing-share.com/app/user?op=share;sc_p=xing-share;url={{url absolute="true"}}">
    Xing
</a>

VK

<a href="https://vk.com/share.php?url={{url absolute="true"}}&title={{encode title}}&description={{excerpt words="45"}}{{#if image}}&image={{@blog.url}}{{image}}{{/if}}&noparse=true">
    VK
</a>

buffer

<a href="https://bufferapp.com/add/?url={{url absolute="true"}}&text={{excerpt words="20"}}">
    Buffer
</a>

StumbleUpon

<a href="https://www.stumbleupon.com/submit?url={{url absolute="true"}}%2F&title={{encode title}}">
    StumbleUpon
</a>

新浪微博 (Sina Weibo)

<a href="http://service.weibo.com/share/share.php?url={{url absolute="true"}}&title={{encode title}}%0D%0A{{excerpt words="20"}}%20{{tags prefix="%23" separator="%23 %23" suffix="%23" autolink="false"}}{{#if image}}&pic={{@blog.url}}{{image}}{{/if}}">
    新浪微博
</a>

Baidu空间

<a href="http://hi.baidu.com/pub/show/share?url={{url absolute="true"}}&title={{encode title}}">
    Baidu空间
</a>

人人网 (Renren)

<a href="http://share.renren.com/share/buttonshare?link={{url absolute="true"}}&title={{encode title}}">
    人人网
</a>

腾讯微博 (QQ Tencent Weibo)

<a href="http://v.t.qq.com/share/share.php?title={{encode title}}%3A%20{{excerpt words="20"}}%20{{tags prefix="%23" separator="%23 %23" suffix="%23" autolink="false"}}&url={{url absolute="true"}}">
    腾讯微博
</a>

QQ空间

<a href="http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?title={{encode title}}&url={{url absolute="true"}}&summary={{excerpt words="20"}}">
    QQ空间
</a>

腾讯朋友网 (Pengyou)

<a href="http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?to=pengyou&title={{encode title}}&url={{url absolute="true"}}&summary={{excerpt words="20"}}">
    腾讯朋友网
</a>

And there you have it. Share links that you can copy and paste into your theme. Now if you're wondering what they look like in the wild, well here they are- maybe try clicking one and share this post yourself.

]]>
<![CDATA[Add Share Links to Ghost Themes]]>

Seems like the internet is all about sharing these days. Back in my day it was a place for the anti-social people to not-really-get-together, but I digress. The ability to share content instantly and effortlessly is powerful. Today we'll take a look at adding share links to a Ghost theme's

]]>
https://iyware.com/add-share-links-to-ghost-themes/5a513273533fe1b5bec542aaMon, 16 Mar 2015 05:51:24 GMT

Seems like the internet is all about sharing these days. Back in my day it was a place for the anti-social people to not-really-get-together, but I digress. The ability to share content instantly and effortlessly is powerful. Today we'll take a look at adding share links to a Ghost theme's handlebars template files, and to make things easier for you I'll provide some basic templates that you can simply copy and paste.

Share vs. Follow vs. Like

First we need to differentiate between "share", "like", and "follow". Share links provide an easy way to repost, send, or otherwise disseminate the content of a post via a third-party channel. Like, and its kin (+1, prop, gild) provide a way to show a sense of solidarity with an idea or the content of the post. And "follow" links provide a way for you to see what content the author is creating on the current platform or another platform.

No-Cost Sharing

This article will be talking about the first option, that is "share" links. We'll look at how to provide links to a variety of various social networks directly in your post template to facilitate the distribution of your post content.

Specifially we will be looking at what I call "no-cost" sharing options. By no-cost I mean that they require no extra resources (JS, images, etc...) and no extra HTTP requests. These are simply links to third-party networks with URL queries crafted to pass the data to the remote site. As a result adding these share links will add no over-head to your site for you or for your users, which is important especially if they're in a country with restricted internet access (like me).

The information for these share links was pieced together from all over the web (other blogs, development API docs) but all of the porting to handlebars was done by me and more than a few were engineered by me- meaning I couldn't find a working example of how to share to a certian social network, so I built it.

Getting Started with Post.hbs

We'll be specifically adding our sharing links to post.hbs because 1) it's the logical option- that's where the content you want to share is! and 2) it's exposed to the {{post}} API in ghost.

So navigate to your theme folder inside of your ghost installation, find post.hbs and open it in your favorite editor. Ghost uses handlebars to dynamically inject specific content into specific tag areas so you won't actually see anything that you've written in ghost inside of your template file. Instead of the title of your post you'll see something like {{title}} and instead of the actual post content you'll see {{content}}.

You'll need to play around with where you want the links to go and how you want to style them, but it's inside of this file that we will be adding them.

Build Links with Ghost APIs

We will be using several Ghost theme APIs to construct our sharing links. Briefly they are:

{{@blog.url}}

This is the FQDN of your blog. For example, on this website {{@blog.url}} resolves to https://iyware.com

{{url absolute="true"}}

This is the complete url to a post on Ghost. For example, on this post {{url absolute="true"}} would output https://iyware.com/add-share-links-to-ghost-themes

{{@blog.title}}

This is the title of your blog which can be set under Ghost → Settings → General like this:

For example, for this website {{@blog.title}} is set to "iyWare". Please do not confuse this with the title of your post, which we'll cover below.

{{title}}

This is the title of the post that you are writing. For example {{title}} on this post is "Add Share Links to Ghost Themes".

{{excerpt}}

The {{excerpt}} function allows you to specific a specific amount of words from the beginning of a post without formatting, meaning no headings, links, italics, etc. You must specificy the number words that you want to include in the excerpt using the words="##" parameter. For example using {{excerpt words="25"}} on this post would return the following:

Seems like the internet is all about sharing these days. Back in my day it was a place for the anti-social people to not-really-get-together, but

Notice tha the word anti-social is not emphasized like it is in this article.

{{tags}}

The {{tags}} API simply returns an alphabetical list of tags associated with a post, but we'll be using some cool parameters later to manipulate their appearance. Unfortunately at this time they can only be output in alphabetical order. The {{tags}} code on this post simply returns {{Ghost}} with a link to the tag page.

{{image}}

The {{image}} tag provides the relative path to a post's image (if it has one). This post doesn't have a post image but if it did it {{image}} would return /images/2015/03/post-image-name.png. Notice that this is not actually returning the image (or an HTML image tag) to an image but rather a partial relative path.

{{#if }} ... {{/if}}

Finally we'll be the {{#if}} API to selectively output different code dependent upon the parameters that we provide. For example to see if a post has an image associated with it we would use {{#if image}} ... {{/if}} and the code between the opening and closing "ifs" would happen.

Discovering Share APIs

Your best bet to find a network that provides a sharing URL API is to search their developer documents (if they have any) or to look at other software that shares the way you want. Remember, for the sake of this post we're not looking for JavaScript or embeddable widgets, we're just looking for HTML anchor tags.

URL Query Strings

A URL can be provided what's known as a "query string" which is simply a list of variables and values. The query string always begins with ?, followed by a variable name (e.g. title), an equals sign =, and the query value (e.g.

Example Share Link: Pinterest

We'll use pinterest as our first example share link. This is the basic structure of the pinterest share URL with the query string empty:

https://pinterest.com/pin/create/button/?url=&media=&description=

So we'll fill out the query with the following API calls:

  • url={{url absolute="true"}}
  • media={{@blog.url}}{{image}}
  • description={{excerpt words="20"}}

Then we'll wrap the media selector in an {{#if}} block in case there's no image associated with the post.

{{#if image}}&media={{@blog.url}}{{image}}{{/if}}

Notice that the whole query key/value pair are selected, this prevents us from referring a blank image. Finally we wrap it all in an html anchor tag:

<a href="https://pinterest.com/pin/create/button/?{{url absolute="true"}}{{#if image}}&media={{@blog.url}}{{image}}{{/if}}&description={{excerpt words="20"}}">
    Pinterest
</a>

Now when you include the link to pinterest in your post and a user clicks on it the result will be something like this:

Example Share Link: E-Mail

There's no more tried-and-true method of sharing online resources than email so it's crucial to include a mailto: link. We'll skip the "to" part of the URL and allow the user to fill that in themselves as it would require adding a form. Instead let's just fill out the query string:

  • ?&subject={{encode @blog.title}}%3A%20{{encode title}}
  • &body={{encode title}}%0D%0A{{url absolute="true"}}%0D%0A%0D%0A{{excerpt words="45"}}%2E%2E%2E

This will output the blog title followed by the post title in the subject of the email like this: "iyWare: Add Share Links to Ghost Themes" and the body will be populated with the post title, URL, and excerpt of the post. Now let's wrap it in an anchor element:

<a class="Email" href="mailto:?&subject={{encode @blog.title}}%3A%20{{encode title}}&body={{encode title}}%0D%0A{{url absolute="true"}}%0D%0A%0D%0A{{excerpt words="45"}}%2E%2E%2E">
    Email
</a>

Now when a user clicks on the "email" link their default mail client will open:

In another post I'll provide prebuilt urls for a dozen or so popular social networks that you can just copy and paste into custom theme.

]]>