We released MonaKiosk yesterday, a modern Astro integration for monetizing your content with Polar.sh.
With MonaKiosk, you can easily add paywalls and monetization to your Astro-powered projects. Whether you’re selling blog posts, courses, templates, or subscriptions, MonaKiosk takes care of the heavy lifting so you can focus on creating great content.
Key Features
- Content Paywalls - Protect your premium content with automatic paywall generation
- Flexible Pricing - Support for both one-time purchases and subscriptions
- Simple Setup - Add a few lines to your Astro config and you're ready to go
- Automatic Sync - Your content automatically syncs to Polar at build time
- Built-in Auth - Email-based authentication and session management included
Installation
npm install mona-kiosk
Quick Start
You can find the whole project in demo.
1. Setup Polar
In Polar, configure the environment values required by .env:
POLAR_ACCESS_TOKEN=polar_oat_xxxxxxxxxxxxx
POLAR_ORG_SLUG=your-org-slug
POLAR_ORG_ID=your-org-id
POLAR_SERVER=sandbox # or 'production'
2. Create an Astro Project
For example, run pnpm create astro@latest and choose the blog template.
Then install the required packages:
-
@astrojs/node// or other server adapters mona-kiosk
The following steps use the Astro blog template as the reference.
3. Update Contents
Import PayableMetadata and merge it into the collection you want to protect.
import { PayableMetadata } from "mona-kiosk";
const blog = defineCollection({
...
schema: ({ image }) =>
z.object(...)
.merge(PayableMetadata),
});
Then, update the metadata in a specific content:
---
title: 'Markdown Style Guide'
description: 'Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.'
pubDate: 'Jun 19 2024'
heroImage: '../../assets/blog-placeholder-1.jpg'
price: 100 # Price in cents ($1)
---
Note: the currency field defaults to usd. Polar currently supports USD only, so you can leave it unset for now.
4. Add Integration
In astro.config.mjs:
import { defineConfig } from "astro/config";
import { monaKiosk } from "mona-kiosk";
export default defineConfig({
output: "server", // Required - MonaKiosk needs SSR
integrations: [
monaKiosk({
polar: {
accessToken: process.env.POLAR_ACCESS_TOKEN,
organizationSlug: process.env.POLAR_ORG_SLUG,
organizationId: process.env.POLAR_ORG_ID,
server: (process.env.POLAR_SERVER as "production" | "sandbox") || "sandbox",
},
collections: [
{ include: "src/content/blog/**/*.md" },
],
}),
],
adapter: node({
mode: "standalone",
}),
});
What gets injected:
-
/api/mona-kiosk/checkout- Create checkout session -
/api/mona-kiosk/auth/signin- Email-based sign-in (For internal calling, protect it.) -
/api/mona-kiosk/auth/signout- Sign out -
/api/mona-kiosk/portal- Redirect to Polar customer portal -
/mona-kiosk/signin- Default signin page (Test only, not secure for production)
🚨 SECURITY WARNING: The default
/mona-kiosk/signinpage is provided ONLY for sandbox testing and is NOT secure for production use.It will only be injected when
server: "sandbox"is set AND no customsigninPagePathis configured.For production, you MUST create your own secure sign-in page or use a third-party authentication provider like BetterAuth.
5. Update Page Template
In src/pages/blog/[...slug].astro:
---
import { getEntry, render } from "astro:content";
const { slug } = Astro.params;
const post = await getEntry("blog", slug);
if (!post) return Astro.redirect("/404");
const { Content } = await render(post);
---
<BlogPost {...post.data}>
{!Astro.locals.paywall?.hasAccess && Astro.locals.paywall?.preview ? (
<div set:html={Astro.locals.paywall.preview} />
) : (
<Content />
)}
</BlogPost>
Note: The middleware automatically detects payable content, checks authentication/access, generates previews, and sets Astro.locals.paywall.
6. Build and Preview
npm run dev
Test card: 4242 4242 4242 4242 (any future date, any CVC)
Support Us
You can check out our live paywalled post: MonaKiosk + BetterAuth Integration Guide. It provides a detailed walkthrough on integrating MonaKiosk with BetterAuth and Polar — a valuable resource for advanced users.
If you’d like to support our work, consider purchasing the guide 😉.
Thank you in advance for your support!
For more information, please visit its github repo.
Top comments (0)