Open-source project
cmod/craigstarter avatar
cmod/craigstarter

Craigstarter runs Kickstarter-style goals and tiers on a Shopify shop with metafields

An open source crowdfunding tool built on Shopify

578 stars21 forksLiquidMPL-2.0

At a glance

What is it?
Craigstarter is a set of Liquid snippets and a section for Shopify that implement a crowdfunding campaign using product and variant metafields, so multiple goals and campaign tiers need no paid metafield plugin. The README is equally blunt about what you give up: the money is charged immediately, not when the main goal is met.
Who is it for?
Adopt Craigstarter if you already run a Shopify shop, already have an audience and newsletter, and want campaign goals, tiers and a public funding page on your own domain rather than on a marketplace. Do not adopt it if your campaign depends on money being held until the goal is reached, because the README states Craigstarter charges immediately, and do not adopt it if you have no existing traffic, since the Kickstarter ecosystem it gives up is what supplies the reach.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 100 days ago.
What is it written in?
Mainly Liquid, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Campaign state lives in product and variant metafields, not in a plugin

Craigstarter is a set of Liquid files for a Shopify theme, and the entire configuration of a campaign lives in Shopify metafields. That single decision is what removes the monthly fee the README complains about, since Shopify supports metafields natively in the admin and no plugin is needed.

The metafield editing route is the admin path. You go to Settings, then Custom data, and create definitions for Products and Variants using the field names the templates expect, with a namespace and key like global.fundingcampaign and global.goalamounts. The type is Single line text for all of them, because the templates read them as plain strings, except campaigninfo which can be Multi-line text. Once the definitions exist, the fields appear at the bottom of every product and variant page in the admin, ready to be filled in.

The product-level fields are the campaign's configuration. fundingcampaign is TRUE for a running campaign, and the README is explicit that the campaign code will not execute unless this is set to true. campaignenddate is the end time in the format YEAR-MO-DA HR:MN, for example 2020-08-15 22:30. totalavailableproducts is how many total products you are selling with all variants inclusive. goalamounts defines the number of goals and the sales amount per goal in a comma-separated list, for example 100, 250, 500. goaltext gives the text for each goal in the same positional format, for example to print, to signed, to postcards, and goaltextcomplete is the text shown once you pass 100 percent for a given goal. campaigninfo is a text blob below the goals that can contain HTML. subtitle and author are optional fields displayed beneath the product title.

The variant-level fields are the tier configuration. variantdescription is the extended description in the selection box, and totalquantity is the total number of available items for that variant, with sales calculated as totalquantity minus remaining inventory.

That the sales figure is derived rather than stored is worth noting. It means the funding progress on the page reflects Shopify's own inventory count, so a campaign cannot drift out of sync with what is actually purchasable.

The README also mentions a bulk editor shortcut, with a screenshot, though the text describing it is cut off there.

How installation works without being a plugin

The installation is five steps that copy files into your theme and edit two of them, and the README explains the reasoning. It has been made as simple as possible to install and set up without being a plugin, which is what affords you the most flexibility and necessary modifications.

The steps, in the README's own numbering:

text
1. Place `campaign.liquid` into your theme's `snippets` folder.
2. Place `campaign.css` into your theme's `assets` folder.
3. Add `{{ 'campaign.css' | asset_url | stylesheet_tag }}` between the `<head> </head>` tags in `layout/theme.liquid`.
4. Backup your `sections/product-template.liquid` file and replace with the included `sections/product-template.liquid`.
5. Place `snippets/product-template-campaign.liquid` and `snippets/product-template-general.liquid` into your `snippets` folder.

Step 3 is the only line you add by hand, and step 4 is the only one that overwrites existing theme code, which is why the README tells you to back the file up first.

The theme compatibility caveat comes next: the included sections/product-template.liquid file is based on the Simple Shopify theme, and you will have to modify your own product-template.liquid if you are using a different theme. For most shops that means the campaign section will need porting to whatever template the theme uses.

The template split in step 5 is the mechanism for having both kinds of product page. product-template-general.liquid becomes the template rendered for non-crowdfunding campaigns, and product-template-campaign.liquid is rendered when the fundingcampaign metafield is set to true. So one theme serves both ordinary products and campaigns, and the metafield decides which one you get. If you want the campaign bar in your own template instead, the README says the sidebar is rendered with this line in product-template:

liquid
{% render 'campaign', product: product %}

One note on the stylesheet: it is plain CSS, because Shopify deprecated Sass compilation in themes back in 2020, and it includes the .medium-only and .small-only rules that show and hide the proper div for the product description on desktop and mobile, so no theme stylesheet edits are needed for that.

The fee arithmetic that justifies the whole approach

The README's case for building your own campaign rather than using Kickstarter is arithmetic, and it is worth repeating because it explains who the tool is for.

Kickstarter takes about 10 percent. Shopify's payment processing fee is about 2.8 percent. An independent publisher running a campaign can save some $7,000 for every $100,000 of sales by using Craigstarter instead of Kickstarter, and the README calls that meaningfully significant, especially in the world of books.

That saving only exists for someone who already has the three things the README names as prerequisites for skipping a marketplace: a community built up, communication channels in place such as a newsletter, and an online shop already running. With those in place, Kickstarter is unnecessarily cumbersome, and the fee is the part that hurts most.

The listed benefits follow from that position. It is free to use and modify, you only pay Shopify's payments fee, you get multiple goals without resorting to stretch goals that lack progress indicators, you get total customization of design, and completed campaigns live on your own website rather than on Kickstarter's. That last one matters for a publisher, because the campaign page stays on the shop's domain and in the shop's own history rather than becoming a dead archive link.

The cost of that is the network effect. The README concedes that Kickstarter is better in many ways, starting with the ecosystem that offers network and community effects around PR and amplification of the campaign, and that Kickstarter is simpler to set up since it hosts and runs the campaign for you.

The same paragraph is candid about the structural limit: Kickstarter payments only happen when the main campaign goal is reached, while Craigstarter charges immediately. The author's proposed workaround is to authorize charges at checkout but push them through only on shipping, which would approximate the Kickstarter experience, but the author notes these charge authorizations are short lived and that this would only work for quick campaigns.

Multiple goals read positionally from two comma-separated lists

The multi-goal system is the part of Craigstarter that Kickstarter cannot match directly, and it is implemented with two parallel comma-separated lists rather than a structured field.

goalamounts holds the thresholds and goaltext holds the matching labels, so a campaign with three goals needs three amounts and three texts, in the same order. The example pairs amounts of 100, 250 and 500 with texts like to print, to signed and to postcards, and goaltextcomplete supplies a separate line for each goal that appears once that goal passes 100 percent of its amount.

This is simple to set up in the admin and simple to read in Liquid, but it has a failure mode. Because the lists are positional and there is no validation between them, a mismatch in length produces a goal with an amount and no text, or a text with no amount. The README does not describe any validation, so the check falls to whoever fills in the fields.

The absence of stretch goals is the point of the design. The README frames shared goals and a sense of reaching a shared target as incentives for consolidated and immediate action, and says you do not have to resort to stretch goals without progress indicators. In the Kickstarter model, a stretch goal is an extra threshold with no running feedback until it is hit. Here every goal has its own amount and its own text, so each threshold says what it buys when it is reached.

The end date has the same simplicity. campaignenddate is a single timestamp in a fixed format, so the countdown logic in the snippet has one value to read, and setting it to true without a valid date is the kind of mistake that shows up as a broken campaign rather than an error.

Everything the campaign page displays comes from these fields plus Shopify's own inventory, which is why the installation involves no code changes beyond the template swap.

Running a campaign below the goal means refunding by hand

The README does not pretend this problem away, and the discussion is one of the more useful parts of the documentation.

Many Kickstarter campaigns are run as promotional tools more than strict fundraising tools, with the intent by creators to ship no matter what. The proposed workaround for Craigstarter's immediate charging is to set a minimum goal on Shopify, and if the goal is not met, manually refund all the backers minus the roughly 2.8 percent processing fees. The README points to a real instance of this pattern in Robin Sloan's 2020 Sloanstarter campaign.

So the operating model is: money moves at checkout, the campaign ends at the deadline, and the refund is a manual operation you perform if the threshold was not reached. The processing fees are not returned, so the residual cost of a failed campaign is roughly 2.8 percent of the gross.

This is where the tool's simplicity becomes a burden. A marketplace handles the escrow, the authorisation expiry, the refunds and the dispute process. Here the merchant handles the refunds through the Shopify admin, for every backer, in the window after the campaign closes.

The README's own closing assessment softens the issue with an observation that is really an argument about the kind of campaign this suits: if you have an audience and reasonable baseline goals, then the issue of raising enough funds for a project launch is often not an issue. In other words, the tool assumes the campaign is very likely to succeed, and the refund path is the exception rather than the plan.

A second, smaller point belongs here too. Kickstarter has tools for following up, providing campaign updates and community communication, and the README lists that among the things Kickstarter does better. Craigstarter does not include a campaign update mechanism, so updates are ordinary Shopify content: a product description edit, a blog post, a page, whatever your theme supports.

Where Craigstarter is the wrong tool

Three limits, and the first is the one that decides everything.

The first is that you need traffic you already own. The README's prerequisites are a community, communication channels and a running shop, and the first listed Kickstarter advantage is its network and community effects around PR and amplification. Craigstarter replaces a marketplace's audience with your own audience and takes away the marketplace's discovery. A creator with no newsletter and no shop has nothing to bring to it, because the tool is not a source of demand.

The second is the immediate charging problem, and it is bigger for books and physical goods than for digital ones. A campaign where the money is charged at checkout and then refunded manually after the fact is a different customer experience from one where funds are held until the goal is reached, and the author says the short-lived authorisation workaround only works for quick campaigns. Any campaign with a long production timeline is exposed.

The third is the theme coupling. The included product template is based on the Simple theme, so on any other theme you are porting the section yourself, and you maintain that port as the theme updates. There is no plugin boundary here, which is exactly what gives you the flexibility and also what leaves you maintaining the integration. A plugin that Shopify updates is a different proposition from a snippet you merge by hand each time the theme changes.

The alternative approach is a dedicated Shopify crowdfunding app, which the README names as the thing being avoided. The difference in approach is that an app handles the escrow-like flow, the authorisation lifetime, the backer communication and possibly a share of the audience, in exchange for a monthly fee and a plugin dependency, whereas Craigstarter gives you the fee difference and the design control and leaves the operational parts to you. For a publisher with a mailing list and a real backlist, the economics favour Craigstarter by the $7,000 per $100,000 the README calculates, and the operational burden is the price of that margin.

The project is small and specific: a Liquid snippet, a stylesheet, three templates and a README, released under the Mozilla Public License 2.0, made by Craig Mod and supported by SPECIAL PROJECTS, with the last push on 2026-07-16 and no GitHub releases. There is no package to install and no version to pin beyond the copy in your theme.

Editorial conclusion

Adopt Craigstarter if you already run a Shopify shop, already have an audience and newsletter, and want campaign goals, tiers and a public funding page on your own domain rather than on a marketplace. Do not adopt it if your campaign depends on money being held until the goal is reached, because the README states Craigstarter charges immediately, and do not adopt it if you have no existing traffic, since the Kickstarter ecosystem it gives up is what supplies the reach. Verify first that the campaign product uses the included sections/product-template.liquid, which is based on the Simple theme, that you define the metafields under Settings then Custom data with the global namespace and the Single line text type, and that your goal amounts and goal text lists have matching lengths, since they are comma-separated and read positionally.

Frequently asked questions

How do I install Craigstarter on my Shopify theme?

Copy campaign.liquid into the theme's snippets folder, campaign.css into assets, add the stylesheet tag line to layout/theme.liquid, back up and replace sections/product-template.liquid with the included one, and copy product-template-campaign.liquid and product-template-general.liquid into snippets. The included product template is based on the Simple theme, so another theme needs porting.

Do I need a paid metafield plugin to use Craigstarter?

No. Shopify supports metafields natively in the admin, so you create definitions under Settings then Custom data for Products and Variants, using the Single line text type, and the fields appear on every product and variant page ready to be filled in.

Which metafields do I need to configure for a Craigstarter campaign?

On the product: fundingcampaign set to true, campaignenddate, totalavailableproducts, goalamounts, goaltext, goaltextcomplete, campaigninfo, and optionally subtitle and author. On the variant: variantdescription and totalquantity. The code will not execute unless fundingcampaign is true.

What happens to the money if a Craigstarter campaign misses its goal?

Craigstarter charges immediately, unlike Kickstarter which only charges when the main goal is reached. The README's workaround is to set a minimum goal and manually refund all backers afterwards, minus the roughly 2.8 percent processing fees, and it notes that authorizing charges at checkout and pushing them through on shipping only works for quick campaigns.

How do multiple funding goals work in Craigstarter?

goalamounts holds the thresholds as a comma-separated list and goaltext holds the matching labels in the same order, with goaltextcomplete supplying the text shown once each goal passes 100 percent. The point is that every goal carries its own progress indicator, rather than a stretch goal with no feedback until it is reached.

How does the fee compare between Craigstarter and Kickstarter?

The README says Craigstarter costs only Shopify's payment processing fee of about 2.8 percent against Kickstarter's roughly 10 percent, and estimates an independent publisher saves around $7,000 for every $100,000 of sales. It also lists Kickstarter's network effects and its campaign update tools among the things it does better.

Official sources

  1. cmod/craigstarter on GitHub
  2. Issues
  3. License: MPL-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cmod-craigstarter.svg)](https://hysenlabs.com/projects/cmod-craigstarter)

Was this useful?