tailprint 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +160 -2
- package/dist/config/env.d.ts +77 -0
- package/dist/config/env.js +38 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/plans.d.ts +15 -0
- package/dist/config/plans.js +104 -0
- package/dist/config/plans.js.map +1 -0
- package/dist/config/templates.d.ts +10 -0
- package/dist/config/templates.js +746 -0
- package/dist/config/templates.js.map +1 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.js +897 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/stdio.d.ts +2 -0
- package/dist/mcp/stdio.js +27 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/routes/dashboard.d.ts +2 -0
- package/dist/routes/dashboard.js +454 -0
- package/dist/routes/dashboard.js.map +1 -0
- package/dist/routes/mcp.d.ts +2 -0
- package/dist/routes/mcp.js +329 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/render.d.ts +2 -0
- package/dist/routes/render.js +444 -0
- package/dist/routes/render.js.map +1 -0
- package/dist/routes/scrape.d.ts +2 -0
- package/dist/routes/scrape.js +132 -0
- package/dist/routes/scrape.js.map +1 -0
- package/dist/routes/templates.d.ts +2 -0
- package/dist/routes/templates.js +2449 -0
- package/dist/routes/templates.js.map +1 -0
- package/dist/routes/usage.d.ts +31 -0
- package/dist/routes/usage.js +73 -0
- package/dist/routes/usage.js.map +1 -0
- package/dist/routes/webhooks.d.ts +2 -0
- package/dist/routes/webhooks.js +227 -0
- package/dist/routes/webhooks.js.map +1 -0
- package/dist/schemas/render.d.ts +422 -0
- package/dist/schemas/render.js +91 -0
- package/dist/schemas/render.js.map +1 -0
- package/dist/schemas/scrape.d.ts +65 -0
- package/dist/schemas/scrape.js +24 -0
- package/dist/schemas/scrape.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +206 -0
- package/dist/server.js.map +1 -0
- package/dist/services/browser.d.ts +21 -0
- package/dist/services/browser.js +299 -0
- package/dist/services/browser.js.map +1 -0
- package/dist/services/carousel.d.ts +43 -0
- package/dist/services/carousel.js +300 -0
- package/dist/services/carousel.js.map +1 -0
- package/dist/services/chart.d.ts +29 -0
- package/dist/services/chart.js +129 -0
- package/dist/services/chart.js.map +1 -0
- package/dist/services/eInvoice.d.ts +62 -0
- package/dist/services/eInvoice.js +413 -0
- package/dist/services/eInvoice.js.map +1 -0
- package/dist/services/email.d.ts +24 -0
- package/dist/services/email.js +177 -0
- package/dist/services/email.js.map +1 -0
- package/dist/services/mockup.d.ts +14 -0
- package/dist/services/mockup.js +130 -0
- package/dist/services/mockup.js.map +1 -0
- package/dist/services/pdfStamper.d.ts +16 -0
- package/dist/services/pdfStamper.js +47 -0
- package/dist/services/pdfStamper.js.map +1 -0
- package/dist/services/qr.d.ts +20 -0
- package/dist/services/qr.js +44 -0
- package/dist/services/qr.js.map +1 -0
- package/dist/services/redis.d.ts +65 -0
- package/dist/services/redis.js +318 -0
- package/dist/services/redis.js.map +1 -0
- package/dist/services/scraper.d.ts +16 -0
- package/dist/services/scraper.js +138 -0
- package/dist/services/scraper.js.map +1 -0
- package/dist/services/storage.d.ts +38 -0
- package/dist/services/storage.js +123 -0
- package/dist/services/storage.js.map +1 -0
- package/dist/services/stripe.d.ts +32 -0
- package/dist/services/stripe.js +229 -0
- package/dist/services/stripe.js.map +1 -0
- package/dist/services/visualDiff.d.ts +33 -0
- package/dist/services/visualDiff.js +218 -0
- package/dist/services/visualDiff.js.map +1 -0
- package/package.json +74 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tailprint (tailprint.com)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,161 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Tailprint — Tailwind-Native Render & PDF Engine + AI Web Scraper
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://modelcontextprotocol.io)
|
|
5
|
+
[](https://tailprint.com)
|
|
6
|
+
[](https://tailprint.com/docs)
|
|
7
|
+
|
|
8
|
+
**Tailprint** ([tailprint.com](https://tailprint.com)) is a high-performance, developer-first rendering engine and Model Context Protocol (MCP) server. It accepts raw HTML styled with arbitrary **Tailwind CSS** utility classes and compiles print-ready, pixel-perfect vector **PDFs** or high-resolution **Open Graph images** in under 800ms.
|
|
9
|
+
|
|
10
|
+
It also features an intelligent **LLM Web Scraper** that strips ads, trackers, and navigation boilerplate using Mozilla Readability, returning token-efficient structured Markdown.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## ⚡ Highlights
|
|
15
|
+
|
|
16
|
+
- **Tailwind-Native:** Built-in Tailwind CSS JIT compilation—no build step, PostCSS config, or bundling required.
|
|
17
|
+
- **Model Context Protocol (MCP):** Connects natively to **Claude Desktop**, **Cursor**, **Windsurf**, and autonomous AI agents via Remote SSE or Stdio CLI.
|
|
18
|
+
- **Sub-800ms Playwright Engine:** Pre-warmed Chromium instances with isolated browser contexts and strict concurrency throttling (`p-limit`).
|
|
19
|
+
- **Interactive Live Playground:** Test markup in real-time in the browser at [tailprint.com](https://tailprint.com).
|
|
20
|
+
- **Free Developer Sandbox:** 100 free monthly renders with zero credit card required.
|
|
21
|
+
- **SHA-256 Deduplication Caching:** Instant cache hits (`X-Cache: HIT`) for repeated image renders.
|
|
22
|
+
- **SSRF & Network Sandboxing:** Automatically blocks local and private IP ranges (`127.0.0.1`, `10.0.0.0/8`, `169.254.169.254`, etc.).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 🤖 Model Context Protocol (MCP) Setup
|
|
27
|
+
|
|
28
|
+
Tailprint provides an official MCP server enabling AI coding assistants and agents to generate documents and scrape web pages on command.
|
|
29
|
+
|
|
30
|
+
### Capabilities & Tools
|
|
31
|
+
1. `render_pdf`: Generates vector PDFs from raw HTML + Tailwind CSS (invoices, certificates, summaries).
|
|
32
|
+
2. `render_image`: Renders 1200x630 social preview cards (PNG/JPEG) with automatic caching.
|
|
33
|
+
3. `scrape_markdown`: Scrapes any public URL, strips web noise, and returns clean Markdown with token metrics.
|
|
34
|
+
|
|
35
|
+
### 1. Claude Desktop Setup
|
|
36
|
+
Add this to your Claude Desktop configuration file:
|
|
37
|
+
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
38
|
+
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"mcpServers": {
|
|
43
|
+
"tailprint": {
|
|
44
|
+
"url": "https://tailprint.com/v1/mcp/sse",
|
|
45
|
+
"headers": {
|
|
46
|
+
"Authorization": "Bearer YOUR_TAILPRINT_API_KEY"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
*(Get a free key at [tailprint.com](https://tailprint.com) with 100 renders/month, no credit card required).*
|
|
53
|
+
|
|
54
|
+
### 2. Cursor IDE Setup
|
|
55
|
+
In Cursor:
|
|
56
|
+
1. Open **Settings** ➔ **Features** ➔ **MCP Servers**.
|
|
57
|
+
2. Click **Add New MCP Server**.
|
|
58
|
+
3. Name: `tailprint`
|
|
59
|
+
4. Type: `sse`
|
|
60
|
+
5. URL: `https://tailprint.com/v1/mcp/sse?api_key=YOUR_TAILPRINT_API_KEY`
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 💰 Pricing & Plans
|
|
65
|
+
|
|
66
|
+
| Tier | Price | Monthly Limit | Features |
|
|
67
|
+
| :--- | :--- | :--- | :--- |
|
|
68
|
+
| **Developer Free** | **$0** | **100 renders** | No credit card required. Full Tailwind support, MCP access. |
|
|
69
|
+
| **Starter** | **$14 / mo** | **2,500 renders** | Ideal for solo developers, indie projects, and small stores. |
|
|
70
|
+
| **Pro (Most Popular)** | **$39 / mo** | **20,000 renders** | Prioritized Chromium queue, SHA-256 caching, agency ready. |
|
|
71
|
+
| **Business / Scale** | **$99 / mo** | **75,000 renders** | High throughput pool reservation, multi-key team access. |
|
|
72
|
+
| **Enterprise** | **$199+ / mo** | **100,000+ renders** | Dedicated browser instances, 99.9% uptime SLA, Slack channel. |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🚀 API Quickstart
|
|
77
|
+
|
|
78
|
+
### 1. Claim a Free API Key (No Credit Card)
|
|
79
|
+
```bash
|
|
80
|
+
curl -X POST https://tailprint.com/v1/auth/claim-free-key \
|
|
81
|
+
-H "Content-Type: application/json" \
|
|
82
|
+
-d '{"email":"your-email@example.com"}'
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 2. Render HTML to PDF
|
|
86
|
+
```bash
|
|
87
|
+
curl -X POST https://tailprint.com/v1/render/pdf \
|
|
88
|
+
-H "Authorization: Bearer sec_live_..." \
|
|
89
|
+
-H "Content-Type: application/json" \
|
|
90
|
+
-d '{
|
|
91
|
+
"html": "<div class=\"p-12 bg-slate-900 text-white font-sans\"><h1 class=\"text-3xl font-bold text-indigo-400\">Invoice #1042</h1><p class=\"text-slate-400 mt-2\">Styled dynamically with Tailwind CSS.</p></div>",
|
|
92
|
+
"format": "A4",
|
|
93
|
+
"landscape": false
|
|
94
|
+
}' \
|
|
95
|
+
--output invoice.pdf
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3. Render Open Graph Social Image
|
|
99
|
+
```bash
|
|
100
|
+
curl -X POST https://tailprint.com/v1/render/image \
|
|
101
|
+
-H "Authorization: Bearer sec_live_..." \
|
|
102
|
+
-H "Content-Type: application/json" \
|
|
103
|
+
-d '{
|
|
104
|
+
"html": "<div class=\"w-full h-full flex flex-col justify-center items-center bg-gradient-to-tr from-indigo-900 to-purple-950 text-white\"><h1 class=\"text-5xl font-black\">Hello Tailprint</h1></div>",
|
|
105
|
+
"width": 1200,
|
|
106
|
+
"height": 630,
|
|
107
|
+
"type": "png"
|
|
108
|
+
}' \
|
|
109
|
+
--output og-card.png
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 4. Scrape Web Page to LLM-Clean Markdown
|
|
113
|
+
```bash
|
|
114
|
+
curl -X POST https://tailprint.com/v1/scrape/markdown \
|
|
115
|
+
-H "Authorization: Bearer sec_live_..." \
|
|
116
|
+
-H "Content-Type: application/json" \
|
|
117
|
+
-d '{
|
|
118
|
+
"url": "https://techcrunch.com/2026/02/10/example-article",
|
|
119
|
+
"strip_images": true
|
|
120
|
+
}'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 🛠 Local Development & Self-Hosting
|
|
126
|
+
|
|
127
|
+
### Requirements
|
|
128
|
+
- Node.js 20+
|
|
129
|
+
- Playwright Chromium (`npx playwright install chromium`)
|
|
130
|
+
- Upstash Redis or local Redis (optional, includes in-memory dev fallback)
|
|
131
|
+
|
|
132
|
+
### Installation
|
|
133
|
+
```bash
|
|
134
|
+
# Clone the repository
|
|
135
|
+
git clone https://github.com/coheroseb/tailprint.git
|
|
136
|
+
cd tailprint
|
|
137
|
+
|
|
138
|
+
# Install dependencies
|
|
139
|
+
npm install
|
|
140
|
+
npx playwright install chromium
|
|
141
|
+
|
|
142
|
+
# Copy environment variables
|
|
143
|
+
cp .env.example .env
|
|
144
|
+
|
|
145
|
+
# Run development server with hot-reload
|
|
146
|
+
npm run dev
|
|
147
|
+
|
|
148
|
+
# Run unit & integration test suite
|
|
149
|
+
npm test
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Docker
|
|
153
|
+
```bash
|
|
154
|
+
docker compose up -d --build
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 📄 License
|
|
160
|
+
|
|
161
|
+
MIT © [Tailprint](https://tailprint.com)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const envSchema: z.ZodObject<{
|
|
3
|
+
NODE_ENV: z.ZodDefault<z.ZodEnum<["development", "production", "test"]>>;
|
|
4
|
+
PORT: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
HOST: z.ZodDefault<z.ZodString>;
|
|
6
|
+
UPSTASH_REDIS_REST_URL: z.ZodOptional<z.ZodString>;
|
|
7
|
+
UPSTASH_REDIS_REST_TOKEN: z.ZodOptional<z.ZodString>;
|
|
8
|
+
STRIPE_SECRET_KEY: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
9
|
+
STRIPE_WEBHOOK_SECRET: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
10
|
+
STRIPE_PRICE_STARTER: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
11
|
+
STRIPE_PRICE_PRO: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
12
|
+
STRIPE_PRICE_BUSINESS: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
13
|
+
STRIPE_PRICE_ENTERPRISE: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
14
|
+
APP_URL: z.ZodDefault<z.ZodString>;
|
|
15
|
+
CONCURRENCY_LIMIT: z.ZodDefault<z.ZodNumber>;
|
|
16
|
+
RENDER_TIMEOUT_MS: z.ZodDefault<z.ZodNumber>;
|
|
17
|
+
CACHE_TTL_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
18
|
+
STORAGE_PATH: z.ZodDefault<z.ZodString>;
|
|
19
|
+
TAILWIND_CDN_URL: z.ZodDefault<z.ZodString>;
|
|
20
|
+
DEV_DEFAULT_API_KEY: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
21
|
+
SMTP_HOST: z.ZodDefault<z.ZodString>;
|
|
22
|
+
SMTP_PORT: z.ZodDefault<z.ZodNumber>;
|
|
23
|
+
SMTP_USER: z.ZodOptional<z.ZodString>;
|
|
24
|
+
SMTP_PASS: z.ZodOptional<z.ZodString>;
|
|
25
|
+
SMTP_FROM: z.ZodDefault<z.ZodString>;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
NODE_ENV: "development" | "production" | "test";
|
|
28
|
+
PORT: number;
|
|
29
|
+
HOST: string;
|
|
30
|
+
STRIPE_SECRET_KEY: string;
|
|
31
|
+
STRIPE_WEBHOOK_SECRET: string;
|
|
32
|
+
STRIPE_PRICE_STARTER: string;
|
|
33
|
+
STRIPE_PRICE_PRO: string;
|
|
34
|
+
STRIPE_PRICE_BUSINESS: string;
|
|
35
|
+
STRIPE_PRICE_ENTERPRISE: string;
|
|
36
|
+
APP_URL: string;
|
|
37
|
+
CONCURRENCY_LIMIT: number;
|
|
38
|
+
RENDER_TIMEOUT_MS: number;
|
|
39
|
+
CACHE_TTL_SECONDS: number;
|
|
40
|
+
STORAGE_PATH: string;
|
|
41
|
+
TAILWIND_CDN_URL: string;
|
|
42
|
+
DEV_DEFAULT_API_KEY: string;
|
|
43
|
+
SMTP_HOST: string;
|
|
44
|
+
SMTP_PORT: number;
|
|
45
|
+
SMTP_FROM: string;
|
|
46
|
+
UPSTASH_REDIS_REST_URL?: string | undefined;
|
|
47
|
+
UPSTASH_REDIS_REST_TOKEN?: string | undefined;
|
|
48
|
+
SMTP_USER?: string | undefined;
|
|
49
|
+
SMTP_PASS?: string | undefined;
|
|
50
|
+
}, {
|
|
51
|
+
NODE_ENV?: "development" | "production" | "test" | undefined;
|
|
52
|
+
PORT?: number | undefined;
|
|
53
|
+
HOST?: string | undefined;
|
|
54
|
+
UPSTASH_REDIS_REST_URL?: string | undefined;
|
|
55
|
+
UPSTASH_REDIS_REST_TOKEN?: string | undefined;
|
|
56
|
+
STRIPE_SECRET_KEY?: string | undefined;
|
|
57
|
+
STRIPE_WEBHOOK_SECRET?: string | undefined;
|
|
58
|
+
STRIPE_PRICE_STARTER?: string | undefined;
|
|
59
|
+
STRIPE_PRICE_PRO?: string | undefined;
|
|
60
|
+
STRIPE_PRICE_BUSINESS?: string | undefined;
|
|
61
|
+
STRIPE_PRICE_ENTERPRISE?: string | undefined;
|
|
62
|
+
APP_URL?: string | undefined;
|
|
63
|
+
CONCURRENCY_LIMIT?: number | undefined;
|
|
64
|
+
RENDER_TIMEOUT_MS?: number | undefined;
|
|
65
|
+
CACHE_TTL_SECONDS?: number | undefined;
|
|
66
|
+
STORAGE_PATH?: string | undefined;
|
|
67
|
+
TAILWIND_CDN_URL?: string | undefined;
|
|
68
|
+
DEV_DEFAULT_API_KEY?: string | undefined;
|
|
69
|
+
SMTP_HOST?: string | undefined;
|
|
70
|
+
SMTP_PORT?: number | undefined;
|
|
71
|
+
SMTP_USER?: string | undefined;
|
|
72
|
+
SMTP_PASS?: string | undefined;
|
|
73
|
+
SMTP_FROM?: string | undefined;
|
|
74
|
+
}>;
|
|
75
|
+
export type Env = z.infer<typeof envSchema>;
|
|
76
|
+
export declare const env: Env;
|
|
77
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
dotenv.config();
|
|
4
|
+
const envSchema = z.object({
|
|
5
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
6
|
+
PORT: z.coerce.number().int().positive().default(3000),
|
|
7
|
+
HOST: z.string().default('0.0.0.0'),
|
|
8
|
+
// Upstash Redis
|
|
9
|
+
UPSTASH_REDIS_REST_URL: z.string().url().optional(),
|
|
10
|
+
UPSTASH_REDIS_REST_TOKEN: z.string().optional(),
|
|
11
|
+
// Stripe
|
|
12
|
+
STRIPE_SECRET_KEY: z.string().optional().default('sk_test_placeholder'),
|
|
13
|
+
STRIPE_WEBHOOK_SECRET: z.string().optional().default('whsec_placeholder'),
|
|
14
|
+
STRIPE_PRICE_STARTER: z.string().optional().default('price_starter_test'),
|
|
15
|
+
STRIPE_PRICE_PRO: z.string().optional().default('price_pro_test'),
|
|
16
|
+
STRIPE_PRICE_BUSINESS: z.string().optional().default('price_business_test'),
|
|
17
|
+
STRIPE_PRICE_ENTERPRISE: z.string().optional().default('price_enterprise_test'),
|
|
18
|
+
APP_URL: z.string().default('http://localhost:3000'),
|
|
19
|
+
// Browser & Rendering limits
|
|
20
|
+
CONCURRENCY_LIMIT: z.coerce.number().int().positive().default(5),
|
|
21
|
+
RENDER_TIMEOUT_MS: z.coerce.number().int().positive().default(8000),
|
|
22
|
+
// Caching
|
|
23
|
+
CACHE_TTL_SECONDS: z.coerce.number().int().positive().default(604800), // 7 days
|
|
24
|
+
// Cloud Storage / Hosted Delivery Directory
|
|
25
|
+
STORAGE_PATH: z.string().default(process.env.STORAGE_PATH || 'storage'),
|
|
26
|
+
// Tailwind CDN
|
|
27
|
+
TAILWIND_CDN_URL: z.string().url().default('https://cdn.tailwindcss.com'),
|
|
28
|
+
// Dev bypass (for quick local testing without Redis if needed)
|
|
29
|
+
DEV_DEFAULT_API_KEY: z.string().optional().default('sec_live_dev_test_key_12345'),
|
|
30
|
+
// SMTP Email Server (Fortrolig.dk)
|
|
31
|
+
SMTP_HOST: z.string().default('mail.fortrolig.dk'),
|
|
32
|
+
SMTP_PORT: z.coerce.number().default(465),
|
|
33
|
+
SMTP_USER: z.string().optional(),
|
|
34
|
+
SMTP_PASS: z.string().optional(),
|
|
35
|
+
SMTP_FROM: z.string().default('Tailprint <noreply@tailprint.com>'),
|
|
36
|
+
});
|
|
37
|
+
export const env = envSchema.parse(process.env);
|
|
38
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface PlanConfig {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
priceUsd: number;
|
|
5
|
+
monthlyLimit: number;
|
|
6
|
+
stripePriceId?: string;
|
|
7
|
+
badge?: string;
|
|
8
|
+
targetAudience: string;
|
|
9
|
+
description: string;
|
|
10
|
+
features: string[];
|
|
11
|
+
}
|
|
12
|
+
export declare const PLANS: Record<string, PlanConfig>;
|
|
13
|
+
export declare const DEFAULT_PLAN: PlanConfig;
|
|
14
|
+
export declare function getPlanById(planId?: string | null): PlanConfig;
|
|
15
|
+
export declare function getPlanByStripePriceId(priceId?: string | null): PlanConfig;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { env } from './env.js';
|
|
2
|
+
export const PLANS = {
|
|
3
|
+
free: {
|
|
4
|
+
id: 'free',
|
|
5
|
+
name: 'Developer Free',
|
|
6
|
+
priceUsd: 0,
|
|
7
|
+
monthlyLimit: 100,
|
|
8
|
+
badge: '100% FREE',
|
|
9
|
+
targetAudience: 'Testing in development, indie hacking & local integration',
|
|
10
|
+
description: 'Instant API key to test Tailprint in your local codebase with zero credit card.',
|
|
11
|
+
features: [
|
|
12
|
+
'100 PDF & image renders / month',
|
|
13
|
+
'Full Tailwind CSS v3 & v4 support',
|
|
14
|
+
'LLM Web Scraper & Markdown API',
|
|
15
|
+
'Model Context Protocol (MCP) access',
|
|
16
|
+
'No credit card required (via Stripe)',
|
|
17
|
+
'1-click instant upgrade to paid',
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
starter: {
|
|
21
|
+
id: 'starter',
|
|
22
|
+
name: 'Starter',
|
|
23
|
+
priceUsd: 14,
|
|
24
|
+
monthlyLimit: 2500,
|
|
25
|
+
stripePriceId: env.STRIPE_PRICE_STARTER,
|
|
26
|
+
targetAudience: 'Solo developers, hobby projects, small e-commerce stores',
|
|
27
|
+
description: 'Zero purchase friction. Get production-grade rendering up and running in minutes.',
|
|
28
|
+
features: [
|
|
29
|
+
'2,500 PDF & image renders / month',
|
|
30
|
+
'Full Tailwind CSS v3 & v4 support',
|
|
31
|
+
'Instant sub-500ms execution',
|
|
32
|
+
'SSRF & network sandbox security',
|
|
33
|
+
'Community & documentation access',
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
pro: {
|
|
37
|
+
id: 'pro',
|
|
38
|
+
name: 'Pro',
|
|
39
|
+
priceUsd: 39,
|
|
40
|
+
monthlyLimit: 20000,
|
|
41
|
+
stripePriceId: env.STRIPE_PRICE_PRO,
|
|
42
|
+
badge: 'MOST POPULAR',
|
|
43
|
+
targetAudience: 'Growing SaaS, agencies with multiple client projects',
|
|
44
|
+
description: 'Higher priority in the Chromium pool with aggressive deduplication caching.',
|
|
45
|
+
features: [
|
|
46
|
+
'20,000 PDF & image renders / month',
|
|
47
|
+
'Prioritized Chromium concurrency queue',
|
|
48
|
+
'7-day SHA-256 image caching (Instant HIT)',
|
|
49
|
+
'Custom paper sizes & print margins',
|
|
50
|
+
'Priority developer support',
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
business: {
|
|
54
|
+
id: 'business',
|
|
55
|
+
name: 'Business / Scale',
|
|
56
|
+
priceUsd: 99,
|
|
57
|
+
monthlyLimit: 75000,
|
|
58
|
+
stripePriceId: env.STRIPE_PRICE_BUSINESS,
|
|
59
|
+
badge: 'BEST VALUE FOR SCALE',
|
|
60
|
+
targetAudience: 'Fast-growing platforms needing scale without sales friction',
|
|
61
|
+
description: 'High-throughput scaling with elevated pool limits and self-service onboarding.',
|
|
62
|
+
features: [
|
|
63
|
+
'75,000 PDF & image renders / month',
|
|
64
|
+
'Elevated concurrency pool reservation',
|
|
65
|
+
'Full webhook & billing automation',
|
|
66
|
+
'Multi-key team access support',
|
|
67
|
+
'Direct Slack / Discord technical channel',
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
enterprise: {
|
|
71
|
+
id: 'enterprise',
|
|
72
|
+
name: 'Enterprise',
|
|
73
|
+
priceUsd: 199,
|
|
74
|
+
monthlyLimit: 100000,
|
|
75
|
+
stripePriceId: env.STRIPE_PRICE_ENTERPRISE,
|
|
76
|
+
targetAudience: 'Large platforms, high volume, custom compliance & SLA',
|
|
77
|
+
description: 'Heavy volume with dedicated browser instances and strict uptime SLA guarantees.',
|
|
78
|
+
features: [
|
|
79
|
+
'100,000+ renders / month',
|
|
80
|
+
'Dedicated Playwright Chromium workers',
|
|
81
|
+
'99.9% availability SLA agreement',
|
|
82
|
+
'Custom pre-loaded font sets & brand assets',
|
|
83
|
+
'Dedicated technical account engineer',
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
export const DEFAULT_PLAN = PLANS.starter;
|
|
88
|
+
export function getPlanById(planId) {
|
|
89
|
+
if (!planId)
|
|
90
|
+
return DEFAULT_PLAN;
|
|
91
|
+
const normalized = planId.toLowerCase().trim();
|
|
92
|
+
return PLANS[normalized] ?? DEFAULT_PLAN;
|
|
93
|
+
}
|
|
94
|
+
export function getPlanByStripePriceId(priceId) {
|
|
95
|
+
if (!priceId)
|
|
96
|
+
return DEFAULT_PLAN;
|
|
97
|
+
for (const plan of Object.values(PLANS)) {
|
|
98
|
+
if (plan.stripePriceId && plan.stripePriceId === priceId) {
|
|
99
|
+
return plan;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return DEFAULT_PLAN;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=plans.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../../src/config/plans.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAc/B,MAAM,CAAC,MAAM,KAAK,GAA+B;IAC/C,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM;QACV,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,CAAC;QACX,YAAY,EAAE,GAAG;QACjB,KAAK,EAAE,WAAW;QAClB,cAAc,EAAE,2DAA2D;QAC3E,WAAW,EAAE,iFAAiF;QAC9F,QAAQ,EAAE;YACR,iCAAiC;YACjC,mCAAmC;YACnC,gCAAgC;YAChC,qCAAqC;YACrC,sCAAsC;YACtC,iCAAiC;SAClC;KACF;IACD,OAAO,EAAE;QACP,EAAE,EAAE,SAAS;QACb,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,GAAG,CAAC,oBAAoB;QACvC,cAAc,EAAE,0DAA0D;QAC1E,WAAW,EAAE,mFAAmF;QAChG,QAAQ,EAAE;YACR,mCAAmC;YACnC,mCAAmC;YACnC,6BAA6B;YAC7B,iCAAiC;YACjC,kCAAkC;SACnC;KACF;IACD,GAAG,EAAE;QACH,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,GAAG,CAAC,gBAAgB;QACnC,KAAK,EAAE,cAAc;QACrB,cAAc,EAAE,sDAAsD;QACtE,WAAW,EAAE,6EAA6E;QAC1F,QAAQ,EAAE;YACR,oCAAoC;YACpC,wCAAwC;YACxC,2CAA2C;YAC3C,oCAAoC;YACpC,4BAA4B;SAC7B;KACF;IACD,QAAQ,EAAE;QACR,EAAE,EAAE,UAAU;QACd,IAAI,EAAE,kBAAkB;QACxB,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,GAAG,CAAC,qBAAqB;QACxC,KAAK,EAAE,sBAAsB;QAC7B,cAAc,EAAE,6DAA6D;QAC7E,WAAW,EAAE,gFAAgF;QAC7F,QAAQ,EAAE;YACR,oCAAoC;YACpC,uCAAuC;YACvC,mCAAmC;YACnC,+BAA+B;YAC/B,0CAA0C;SAC3C;KACF;IACD,UAAU,EAAE;QACV,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,GAAG;QACb,YAAY,EAAE,MAAM;QACpB,aAAa,EAAE,GAAG,CAAC,uBAAuB;QAC1C,cAAc,EAAE,uDAAuD;QACvE,WAAW,EAAE,iFAAiF;QAC9F,QAAQ,EAAE;YACR,0BAA0B;YAC1B,uCAAuC;YACvC,kCAAkC;YAClC,4CAA4C;YAC5C,sCAAsC;SACvC;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;AAE1C,MAAM,UAAU,WAAW,CAAC,MAAsB;IAChD,IAAI,CAAC,MAAM;QAAE,OAAO,YAAY,CAAC;IACjC,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC/C,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,YAAY,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAuB;IAC5D,IAAI,CAAC,OAAO;QAAE,OAAO,YAAY,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,KAAK,OAAO,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC"}
|