prices-as-code
Version:
Prices as Code (PaC) - Define your product pricing schemas with type-safe definitions
407 lines (356 loc) • 12.2 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Getting Started - Prices as Code</title>
<meta name="description" content="Getting started with the Prices as Code TypeScript library">
<link rel="stylesheet" href="../assets/css/main.css">
<link rel="icon" href="https://raw.githubusercontent.com/wickdninja/assets/refs/heads/main/PaC.webp">
</head>
<body>
<header class="site-header">
<div class="container">
<div class="header-content">
<div class="logo">
<a href="../index.html">
<img src="https://raw.githubusercontent.com/wickdninja/assets/refs/heads/main/PaC.webp" alt="Prices as Code" width="40">
<span>Prices as Code</span>
</a>
</div>
<nav class="main-nav">
<ul>
<li><a href="index.html">Guides</a></li>
<li><a href="../api/index.html">API</a></li>
<li><a href="../providers/index.html">Providers</a></li>
<li><a href="https://github.com/wickdninja/prices-as-code" target="_blank">GitHub</a></li>
<li><a href="https://www.npmjs.com/package/prices-as-code" target="_blank">NPM</a></li>
</ul>
</nav>
</div>
</div>
</header>
<main class="content">
<div class="container">
<h1>Getting Started with Prices as Code</h1>
<p>This guide will walk you through setting up Prices as Code and creating your first pricing configuration.</p>
<h2>Installation</h2>
<p>Install the package using npm:</p>
<div class="highlight">
<pre><code class="language-bash">npm install prices-as-code</code></pre>
</div>
<p>Or with yarn:</p>
<div class="highlight">
<pre><code class="language-bash">yarn add prices-as-code</code></pre>
</div>
<p>Or with pnpm:</p>
<div class="highlight">
<pre><code class="language-bash">pnpm add prices-as-code</code></pre>
</div>
<h2>Setup Environment Variables</h2>
<p>Create a <code>.env</code> file in your project root with your API key:</p>
<div class="highlight">
<pre><code># .env file
STRIPE_SECRET_KEY=sk_test_your_stripe_key</code></pre>
</div>
<h2>Create a Configuration File</h2>
<div class="tabs">
<div class="tab active" onclick="showTab('ts')">TypeScript</div>
<div class="tab" onclick="showTab('yaml')">YAML</div>
</div>
<div id="ts-tab" class="tab-content">
<p>Create a <code>pricing.ts</code> file:</p>
<div class="highlight">
<pre><code class="language-typescript">import { Config } from 'prices-as-code';
const config: Config = {
products: [
{
provider: 'stripe',
name: 'Basic Plan',
description: 'For individuals and small teams',
features: ['5 projects', '10GB storage', 'Email support'],
highlight: false,
metadata: {
displayOrder: 1
}
},
{
provider: 'stripe',
name: 'Pro Plan',
description: 'For growing businesses',
features: ['Unlimited projects', '100GB storage', 'Priority support'],
highlight: true,
metadata: {
displayOrder: 2
}
}
],
prices: [
{
provider: 'stripe',
name: 'Basic Monthly',
nickname: 'Basic Monthly',
unitAmount: 999, // $9.99
currency: 'usd',
type: 'recurring',
recurring: {
interval: 'month',
intervalCount: 1
},
productKey: 'basic_plan',
metadata: {
displayName: 'Basic Monthly'
}
},
{
provider: 'stripe',
name: 'Pro Monthly',
nickname: 'Pro Monthly',
unitAmount: 1999, // $19.99
currency: 'usd',
type: 'recurring',
recurring: {
interval: 'month',
intervalCount: 1
},
productKey: 'pro_plan',
metadata: {
displayName: 'Pro Monthly'
}
}
]
};
export default config;</code></pre>
</div>
</div>
<div id="yaml-tab" class="tab-content" style="display: none;">
<p>Create a <code>prices.yml</code> file:</p>
<div class="highlight">
<pre><code class="language-yaml">products:
- provider: stripe
name: Basic Plan
description: For individuals and small teams
features:
- 5 projects
- 10GB storage
- Email support
highlight: false
metadata:
displayOrder: 1
- provider: stripe
name: Pro Plan
description: For growing businesses
features:
- Unlimited projects
- 100GB storage
- Priority support
highlight: true
metadata:
displayOrder: 2
prices:
- provider: stripe
name: Basic Monthly
nickname: Basic Monthly
unitAmount: 999
currency: usd
type: recurring
recurring:
interval: month
intervalCount: 1
productKey: basic_plan
metadata:
displayName: Basic Monthly
- provider: stripe
name: Pro Monthly
nickname: Pro Monthly
unitAmount: 1999
currency: usd
type: recurring
recurring:
interval: month
intervalCount: 1
productKey: pro_plan
metadata:
displayName: Pro Monthly</code></pre>
</div>
<h2>Running the Synchronization</h2>
<h3>Using the CLI</h3>
<p>Sync your configuration using the command-line interface:</p>
<div class="highlight">
<pre><code class="language-bash">npx prices-as-code pricing.ts</code></pre>
</div>
<p>Or for YAML:</p>
<div class="highlight">
<pre><code class="language-bash">npx prices-as-code prices.yml</code></pre>
</div>
<h4>Push Model vs. Write-Back Model</h4>
<p>By default, Prices as Code uses a <strong>Push Model</strong>, where it pushes your configuration to the provider
but doesn't modify your local configuration files. This is useful when:</p>
<ul>
<li>You want to use the same configuration file to push to different environments (dev, staging, production)</li>
<li>You're working with providers that don't allow setting IDs programmatically</li>
<li>You want to maintain a clean separation between your configuration and provider-specific IDs</li>
</ul>
<p>If you prefer the original behavior where provider IDs are written back to your configuration file, use the <code>--write-back</code> flag:</p>
<div class="highlight">
<pre><code class="language-bash">npx prices-as-code prices.yml --write-back</code></pre>
</div>
<h3>Using the JavaScript API</h3>
<p>You can also use the JavaScript API in your own scripts:</p>
<div class="highlight">
<pre><code class="language-typescript">import { pac } from 'prices-as-code';
async function syncPricing() {
try {
const result = await pac({
configPath: './pricing.ts',
providers: [
{
provider: 'stripe',
options: {
secretKey: process.env.STRIPE_SECRET_KEY,
}
}
],
// Set to true to write updated IDs back to config file (legacy behavior)
// Default is false - PUSH mode (push to provider without modifying source)
writeBack: false
});
console.log('Sync result:', result);
} catch (error) {
console.error('Sync failed:', error);
}
}
syncPricing();</code></pre>
</div>
<h2>Sample Configuration</h2>
<div class="sample-config">
<h3>Real-World Example</h3>
<p>Here's a comprehensive example based on a tiered subscription model:</p>
<div class="highlight">
<pre><code class="language-yaml">products:
- name: Free
description: Start your learning journey
metadata:
icon: Book
color: blue
key: free
features:
- Access to free content
- Limited features
- Core lessons
- Ad-supported experience
highlight: false
provider: stripe
key: free
- name: Pro
description: Help us shine bright with new features
metadata:
icon: Star
color: purple
key: pro
features:
- Support ongoing development
- Supporter recognition
- Early access to new features
- Ad-free experience
- Unlimited access
highlight: true
provider: stripe
key: pro
- name: Ultra
description: The ultimate experience
metadata:
icon: Trophy
color: amber
key: ultra
features:
- All Pro perks
- Ultra member recognition
- Input on future features
- Priority support
- Personalized plans
highlight: false
provider: stripe
key: ultra
prices:
- name: Free
unitAmount: 0
currency: usd
type: recurring
recurring:
interval: year
intervalCount: 1
active: true
metadata:
plan_code: free
display_price: $0
nickname: Free plan
provider: stripe
productKey: free
- name: Pro Monthly
unitAmount: 1000
currency: usd
type: recurring
recurring:
interval: month
intervalCount: 1
active: true
metadata:
plan_code: pro_monthly
display_price: $10
nickname: Pro Monthly Plan
provider: stripe
productKey: pro
- name: Pro Yearly
unitAmount: 9600
currency: usd
type: recurring
recurring:
interval: year
intervalCount: 1
active: true
metadata:
plan_code: pro_yearly
display_price: $96
nickname: Pro Yearly Plan
provider: stripe
productKey: pro
</code></pre>
</div>
</div>
<h2>Next Steps</h2>
<ul>
<li>Check out <a href="configuration-file.html">Configuration File Format</a> to learn more about config options</li>
<li>Set up <a href="ci-cd.html">CI/CD Integration</a> to automate your pricing updates</li>
<li>Learn about <a href="custom-pricing.html">Custom Pricing Logic</a> for more complex scenarios</li>
<li>Explore <a href="metadata.html">Metadata Usage</a> for enhanced flexibility</li>
</ul>
</div>
</main>
<footer class="site-footer">
<div class="container">
<div class="footer-content">
<p>Copyright © 2025 Nate Ross. Distributed by an <a href="https://github.com/wickdninja/prices-as-code/blob/main/LICENSE">MIT license.</a></p>
<p><a href="#top" class="back-to-top">Back to top</a></p>
</div>
</div>
</footer>
<script src="../assets/js/main.js"></script>
<script>
function showTab(tabId) {
// Hide all tab contents
document.querySelectorAll('.tab-content').forEach(tab => {
tab.style.display = 'none';
});
// Remove active class from all tabs
document.querySelectorAll('.tab').forEach(tab => {
tab.classList.remove('active');
});
// Show the selected tab content
document.getElementById(tabId + '-tab').style.display = 'block';
// Add active class to the clicked tab
document.querySelector(`.tab[onclick="showTab('${tabId}')"]`).classList.add('active');
}
</script>
</body>
</html>