@shipindays/shipindays 0.1.2
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/LICENCE +21 -0
- package/README.md +505 -0
- package/index.js +457 -0
- package/package.json +64 -0
- package/templates/blocks/auth/nextauth/app/api/auth/[...nextauth]/route.ts +19 -0
- package/templates/blocks/auth/nextauth/lib/auth/index.ts +98 -0
- package/templates/blocks/auth/nextauth/middleware.ts +30 -0
- package/templates/blocks/auth/nextauth/package.json +9 -0
- package/templates/blocks/auth/supabase/package.json +6 -0
- package/templates/blocks/auth/supabase/src/lib/auth/index.ts +75 -0
- package/templates/blocks/auth/supabase/src/middleware.ts +54 -0
- package/templates/blocks/email/nodemailer/index.ts +62 -0
- package/templates/blocks/email/nodemailer/package.json +8 -0
- package/templates/blocks/email/resend/index.ts +53 -0
- package/templates/blocks/email/resend/package.json +5 -0
package/LICENCE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nikhil sai ankilla
|
|
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
ADDED
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
# ⚡ create-shipindays
|
|
2
|
+
|
|
3
|
+
> Scaffold a production-ready Next.js SaaS in seconds. Pick your stack, get auth + email wired up and working.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx @shipindays/shipindays@latest my-app
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/org/shipindays/shipindays)
|
|
10
|
+
[](./LICENSE)
|
|
11
|
+
[](https://github.com/nikhilsaiankilla/shipindays)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## What is this?
|
|
16
|
+
|
|
17
|
+
Most SaaS boilerplates give you one fixed stack. You either use it or you don't.
|
|
18
|
+
|
|
19
|
+
`create-shipindays` asks you what you want and builds it for you:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
? Auth provider
|
|
23
|
+
❯ Supabase Auth
|
|
24
|
+
NextAuth v5
|
|
25
|
+
|
|
26
|
+
? Email provider
|
|
27
|
+
❯ Resend
|
|
28
|
+
Nodemailer
|
|
29
|
+
|
|
30
|
+
✓ Auth: supabase injected.
|
|
31
|
+
✓ Email: resend injected.
|
|
32
|
+
✓ Your SaaS is scaffolded.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Every combination produces a working Next.js 15 app with the right files, the right dependencies, and a pre-filled `.env.example`.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## What's included
|
|
40
|
+
|
|
41
|
+
Every scaffold includes:
|
|
42
|
+
|
|
43
|
+
- **Next.js 15** with App Router and TypeScript
|
|
44
|
+
- **Tailwind CSS** + **shadcn/ui** components
|
|
45
|
+
- Auth — your choice of provider
|
|
46
|
+
- Email — your choice of provider
|
|
47
|
+
- Protected `/dashboard` route
|
|
48
|
+
- Login + Signup pages
|
|
49
|
+
- `.env.example` pre-filled for your chosen stack
|
|
50
|
+
- `.gitignore` that won't leak your secrets
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Quick start
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Create a new project
|
|
58
|
+
npx @shipindays/shipindays@latest my-app
|
|
59
|
+
|
|
60
|
+
# Move into it
|
|
61
|
+
cd my-app
|
|
62
|
+
|
|
63
|
+
# Copy env file and fill in your keys
|
|
64
|
+
cp .env.example .env.local
|
|
65
|
+
|
|
66
|
+
# Push database schema (if using Drizzle)
|
|
67
|
+
npm run db:push
|
|
68
|
+
|
|
69
|
+
# Start dev server
|
|
70
|
+
npm run dev
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Supported providers
|
|
76
|
+
|
|
77
|
+
| Feature | Providers |
|
|
78
|
+
|---------|-----------|
|
|
79
|
+
| Auth | Supabase Auth, NextAuth v5 |
|
|
80
|
+
| Email | Resend, Nodemailer |
|
|
81
|
+
|
|
82
|
+
More coming. PRs welcome — see [Contributing](#contributing).
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Support
|
|
87
|
+
|
|
88
|
+
If `create-shipindays` saved you time, consider supporting the project.
|
|
89
|
+
|
|
90
|
+
[](https://buymeacoffee.com/nikhilsaiankilla)
|
|
91
|
+
[](https://ko-fi.com/nikhilsaiankilla)
|
|
92
|
+
|
|
93
|
+
## Hiring
|
|
94
|
+
|
|
95
|
+
I build full stack products and open source tooling. If your team is looking for a developer, let's talk.
|
|
96
|
+
|
|
97
|
+
→ [x.com/itzznikhilsai](https://x.com/itzznikhilsai)
|
|
98
|
+
→ [nikhilsaiankilla@gmail.com](mailto:nikhilsaiankilla@gmail.com)
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## How it works
|
|
103
|
+
|
|
104
|
+
The CLI is built on a **base + blocks** pattern.
|
|
105
|
+
|
|
106
|
+
### Base template
|
|
107
|
+
|
|
108
|
+
`templates/base/` is always copied first. It contains:
|
|
109
|
+
|
|
110
|
+
- The full Next.js app skeleton
|
|
111
|
+
- **Placeholder files** for auth and email that throw errors if called
|
|
112
|
+
- App code that imports from fixed paths (`@/lib/auth`, `@/lib/email`) — these paths never change
|
|
113
|
+
|
|
114
|
+
### Blocks
|
|
115
|
+
|
|
116
|
+
`templates/blocks/<feature>/<provider>/` contains the real implementation for each provider.
|
|
117
|
+
|
|
118
|
+
When you pick a provider, the CLI copies that block's files **on top of the base**. Because both the base placeholder and the block use the same file paths, the block overwrites the placeholder.
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
base/src/lib/auth/index.ts ← placeholder (throws error)
|
|
122
|
+
↑
|
|
123
|
+
blocks/auth/supabase/src/lib/auth/index.ts ← real Supabase implementation
|
|
124
|
+
↑
|
|
125
|
+
copies and overwrites
|
|
126
|
+
↓
|
|
127
|
+
your-project/src/lib/auth/index.ts ← Supabase code, ready to use
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Your app always imports `from "@/lib/auth"`. It never knows or cares which provider is underneath.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Project structure
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
create-shipindays/
|
|
138
|
+
├── index.js ← CLI entry point (the npx command)
|
|
139
|
+
├── package.json ← CLI's own dependencies
|
|
140
|
+
│
|
|
141
|
+
└── templates/
|
|
142
|
+
├── base/ ← always scaffolded first
|
|
143
|
+
│ └── src/
|
|
144
|
+
│ ├── middleware.ts ← placeholder
|
|
145
|
+
│ ├── lib/
|
|
146
|
+
│ │ ├── auth/index.ts ← placeholder
|
|
147
|
+
│ │ └── email/index.ts ← placeholder
|
|
148
|
+
│ └── app/
|
|
149
|
+
│ ├── dashboard/page.tsx
|
|
150
|
+
│ └── (auth)/
|
|
151
|
+
│ ├── login/page.tsx
|
|
152
|
+
│ └── signup/page.tsx
|
|
153
|
+
│
|
|
154
|
+
└── blocks/
|
|
155
|
+
├── auth/
|
|
156
|
+
│ ├── supabase/ ← injected when user picks Supabase Auth
|
|
157
|
+
│ │ ├── package.json
|
|
158
|
+
│ │ └── src/
|
|
159
|
+
│ │ ├── middleware.ts
|
|
160
|
+
│ │ ├── lib/auth/index.ts
|
|
161
|
+
│ │ └── lib/supabase/
|
|
162
|
+
│ │ ├── server.ts
|
|
163
|
+
│ │ └── client.ts
|
|
164
|
+
│ │
|
|
165
|
+
│ └── nextauth/ ← injected when user picks NextAuth v5
|
|
166
|
+
│ ├── package.json
|
|
167
|
+
│ └── src/
|
|
168
|
+
│ ├── middleware.ts
|
|
169
|
+
│ ├── lib/auth/index.ts
|
|
170
|
+
│ └── app/api/auth/
|
|
171
|
+
│ └── [...nextauth]/
|
|
172
|
+
│ └── route.ts ← ONLY nextauth has this
|
|
173
|
+
│
|
|
174
|
+
└── email/
|
|
175
|
+
├── resend/
|
|
176
|
+
│ ├── package.json
|
|
177
|
+
│ └── index.ts
|
|
178
|
+
└── nodemailer/
|
|
179
|
+
├── package.json
|
|
180
|
+
└── index.ts
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Contributing
|
|
186
|
+
|
|
187
|
+
PRs are very welcome. The most valuable contributions are **new provider blocks**.
|
|
188
|
+
|
|
189
|
+
### Setup
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
git clone https://github.com/nikhilsaiankilla/shipindays
|
|
193
|
+
cd shipindays
|
|
194
|
+
npm install
|
|
195
|
+
npm link # makes "create-shipindays" available as a local command
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Test your changes:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
create-shipindays test-app
|
|
202
|
+
cd test-app
|
|
203
|
+
cat src/lib/auth/index.ts # verify the right block was injected
|
|
204
|
+
cat .env.example # verify the right env vars were added
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## How to add a new provider block
|
|
210
|
+
|
|
211
|
+
There are two cases depending on whether your provider needs files at **paths that already exist in base**, or needs **extra files that base doesn't have**.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
### CASE 1 — Provider only needs files that already exist in base
|
|
216
|
+
|
|
217
|
+
**Example: adding Postmark as an email provider.**
|
|
218
|
+
|
|
219
|
+
Postmark only needs `src/lib/email/index.ts` — a file that already exists in base as a placeholder. This is the simple case.
|
|
220
|
+
|
|
221
|
+
**Step 1 — Create the block folder**
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
templates/blocks/email/postmark/
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Step 2 — Add `index.ts` with the exact same exported functions as other email providers**
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
// templates/blocks/email/postmark/index.ts
|
|
231
|
+
|
|
232
|
+
export async function sendWelcomeEmail({ to, name }: { to: string; name: string }) {
|
|
233
|
+
// your Postmark implementation
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export async function sendPasswordResetEmail({ to, resetUrl }: { to: string; resetUrl: string }) {
|
|
237
|
+
// your Postmark implementation
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
> ⚠️ **The exported function names must be identical to every other email block.**
|
|
242
|
+
> The rest of the app calls these functions by name. If the name is different, it breaks.
|
|
243
|
+
|
|
244
|
+
**Step 3 — Add `package.json` with only this provider's dependencies**
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
{
|
|
248
|
+
"dependencies": {
|
|
249
|
+
"postmark": "^4.0.0"
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Step 4 — Register it in `index.js`**
|
|
255
|
+
|
|
256
|
+
Add to `EMAIL_PROVIDERS`:
|
|
257
|
+
|
|
258
|
+
```js
|
|
259
|
+
postmark: {
|
|
260
|
+
label: "Postmark",
|
|
261
|
+
hint: "postmarkapp.com — great deliverability",
|
|
262
|
+
},
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Add to `ENV_VARS.email`:
|
|
266
|
+
|
|
267
|
+
```js
|
|
268
|
+
postmark: {
|
|
269
|
+
"# ── Postmark (Email) ──────────────────────────────────────────────────": [
|
|
270
|
+
"POSTMARK_API_TOKEN=",
|
|
271
|
+
],
|
|
272
|
+
},
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**That's it.** The CLI will show Postmark as an option and inject it correctly.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
### CASE 2 — Provider needs extra files that base doesn't have
|
|
280
|
+
|
|
281
|
+
**Example 1: NextAuth needs `src/app/api/auth/[...nextauth]/route.ts`**
|
|
282
|
+
**Example 2: Supabase needs `src/lib/supabase/server.ts` and `src/lib/supabase/client.ts`**
|
|
283
|
+
|
|
284
|
+
Base doesn't have these files at all. The block needs to add them from scratch.
|
|
285
|
+
|
|
286
|
+
This is handled automatically — the `injectBlock()` function for `auth` blocks copies the **entire `src/` folder** of the block into the project's `src/` folder. So any extra files your block includes just get created.
|
|
287
|
+
|
|
288
|
+
**Step 1 — Create the block folder with a `src/` subfolder**
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
templates/blocks/auth/myauth/
|
|
292
|
+
src/ ← must be named src/
|
|
293
|
+
lib/
|
|
294
|
+
auth/
|
|
295
|
+
index.ts ← replaces base placeholder (required)
|
|
296
|
+
middleware.ts ← replaces base placeholder (required)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Step 2 — Add any extra files your provider needs inside `src/`**
|
|
300
|
+
|
|
301
|
+
For example, if your provider needs a server client and browser client:
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
templates/blocks/auth/myauth/
|
|
305
|
+
src/
|
|
306
|
+
lib/
|
|
307
|
+
auth/
|
|
308
|
+
index.ts ← replaces base placeholder
|
|
309
|
+
myauth/
|
|
310
|
+
server.ts ← EXTRA file — doesn't exist in base, gets created
|
|
311
|
+
client.ts ← EXTRA file — doesn't exist in base, gets created
|
|
312
|
+
middleware.ts ← replaces base placeholder
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
For example, if your provider needs an API route:
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
templates/blocks/auth/myauth/
|
|
319
|
+
src/
|
|
320
|
+
lib/
|
|
321
|
+
auth/
|
|
322
|
+
index.ts
|
|
323
|
+
middleware.ts
|
|
324
|
+
app/
|
|
325
|
+
api/
|
|
326
|
+
auth/
|
|
327
|
+
[...myauth]/
|
|
328
|
+
route.ts ← EXTRA file — gets created in the project
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**Step 3 — The contract: `lib/auth/index.ts` must export these exact 3 functions**
|
|
332
|
+
|
|
333
|
+
No matter what else your block does internally, `src/lib/auth/index.ts` must export:
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
// Every auth block MUST export these 3 functions with these exact signatures.
|
|
337
|
+
// The dashboard, middleware, and login page call these — they never change.
|
|
338
|
+
|
|
339
|
+
export async function getCurrentUser(): Promise<User | null>
|
|
340
|
+
// Returns the logged-in user, or null if not logged in.
|
|
341
|
+
// Used when you want to show different UI for logged-in vs logged-out users.
|
|
342
|
+
|
|
343
|
+
export async function requireUser(): Promise<User>
|
|
344
|
+
// Returns the logged-in user, or redirects to /login if not logged in.
|
|
345
|
+
// Used on any page that requires authentication.
|
|
346
|
+
|
|
347
|
+
export async function signOut(): Promise<void>
|
|
348
|
+
// Signs the user out and redirects to /.
|
|
349
|
+
// Called from logout buttons.
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Step 4 — Add `package.json` with only this provider's dependencies**
|
|
353
|
+
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"dependencies": {
|
|
357
|
+
"my-auth-package": "^1.0.0"
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**Step 5 — Register it in `index.js`**
|
|
363
|
+
|
|
364
|
+
Add to `AUTH_PROVIDERS`:
|
|
365
|
+
|
|
366
|
+
```js
|
|
367
|
+
myauth: {
|
|
368
|
+
label: "MyAuth",
|
|
369
|
+
hint: "Description of your provider",
|
|
370
|
+
},
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Add to `ENV_VARS.auth`:
|
|
374
|
+
|
|
375
|
+
```js
|
|
376
|
+
myauth: {
|
|
377
|
+
"# ── MyAuth ───────────────────────────────────────────────────────────────": [
|
|
378
|
+
"MYAUTH_API_KEY=",
|
|
379
|
+
"MYAUTH_SECRET=",
|
|
380
|
+
],
|
|
381
|
+
},
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**That's it.** The CLI handles everything else — injecting the files, merging deps, writing env vars.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## How `injectBlock()` works internally
|
|
389
|
+
|
|
390
|
+
This is the function that makes the whole system work. Understanding it helps you debug issues.
|
|
391
|
+
|
|
392
|
+
```
|
|
393
|
+
EMAIL blocks:
|
|
394
|
+
Copies block files → project/src/lib/<feature>/
|
|
395
|
+
e.g. blocks/email/resend/index.ts → project/src/lib/email/index.ts
|
|
396
|
+
|
|
397
|
+
AUTH blocks:
|
|
398
|
+
Copies block's src/ folder → project/src/
|
|
399
|
+
e.g. blocks/auth/nextauth/src/middleware.ts → project/src/middleware.ts
|
|
400
|
+
blocks/auth/nextauth/src/lib/auth/index.ts → project/src/lib/auth/index.ts
|
|
401
|
+
blocks/auth/nextauth/src/app/api/auth/[...nextauth]/route.ts → project/src/app/api/auth/[...nextauth]/route.ts
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
`overwrite: true` is set on every copy. This means:
|
|
405
|
+
- Files that exist in base get overwritten by the block (placeholder → real implementation)
|
|
406
|
+
- Files that don't exist in base get created fresh (extra files like API routes)
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## The contract system
|
|
411
|
+
|
|
412
|
+
Every feature has a contract — a set of functions that **every provider for that feature must export**.
|
|
413
|
+
|
|
414
|
+
The rest of the app only ever calls contract functions. It never imports from the provider directly.
|
|
415
|
+
|
|
416
|
+
### Auth contract
|
|
417
|
+
|
|
418
|
+
```ts
|
|
419
|
+
// src/lib/auth/index.ts — every auth block must export these
|
|
420
|
+
export async function getCurrentUser(): Promise<User | null>
|
|
421
|
+
export async function requireUser(): Promise<User>
|
|
422
|
+
export async function signOut(): Promise<void>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Email contract
|
|
426
|
+
|
|
427
|
+
```ts
|
|
428
|
+
// src/lib/email/index.ts — every email block must export these
|
|
429
|
+
export async function sendWelcomeEmail(args: { to: string; name: string }): Promise<void>
|
|
430
|
+
export async function sendPasswordResetEmail(args: { to: string; resetUrl: string }): Promise<void>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
If you add a new email type (e.g. `sendInvoiceEmail`), add it to the base placeholder first, then implement it in every existing email block, then in your new block.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Adding a completely new feature (e.g. payments)
|
|
438
|
+
|
|
439
|
+
Follow this checklist:
|
|
440
|
+
|
|
441
|
+
```
|
|
442
|
+
1. Create block folders:
|
|
443
|
+
templates/blocks/payments/stripe/
|
|
444
|
+
templates/blocks/payments/lemonsqueezy/
|
|
445
|
+
|
|
446
|
+
2. Add placeholder to base:
|
|
447
|
+
templates/base/src/lib/payments/index.ts
|
|
448
|
+
(same pattern — exports functions that throw errors)
|
|
449
|
+
|
|
450
|
+
3. Implement the contract in each block:
|
|
451
|
+
blocks/payments/stripe/index.ts
|
|
452
|
+
blocks/payments/lemonsqueezy/index.ts
|
|
453
|
+
(each must export the same function names)
|
|
454
|
+
|
|
455
|
+
4. Add package.json to each block with its deps
|
|
456
|
+
|
|
457
|
+
5. In index.js:
|
|
458
|
+
a. Add PAYMENT_PROVIDERS object (same shape as EMAIL_PROVIDERS)
|
|
459
|
+
b. Add ENV_VARS.payments object (same shape as ENV_VARS.email)
|
|
460
|
+
c. Add a p.select() prompt in main() for payments
|
|
461
|
+
d. Add choices.payments = paymentsProvider to the choices object
|
|
462
|
+
e. Add injectBlock("payments", choices.payments, targetPath) call
|
|
463
|
+
f. Add mergePackageJson(targetPath, "payments", choices.payments) call
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
## FAQ
|
|
469
|
+
|
|
470
|
+
**Q: Why not just have separate full templates like `create-t3-app`?**
|
|
471
|
+
|
|
472
|
+
Full templates mean if you have 3 auth providers × 3 email providers × 2 payment providers, you need 18 separate templates. Any bug fix needs to be made 18 times. Blocks mean you fix it once.
|
|
473
|
+
|
|
474
|
+
**Q: What if two blocks conflict?**
|
|
475
|
+
|
|
476
|
+
They shouldn't if they respect the contract. Both blocks write to `src/lib/auth/index.ts` but only one is ever injected per project. They never coexist.
|
|
477
|
+
|
|
478
|
+
**Q: What if I want to add a provider that needs to modify an existing file (not just replace it)?**
|
|
479
|
+
|
|
480
|
+
This is the one case blocks don't handle cleanly. For example, if you needed to add a line to `layout.tsx`. For now, document it as a manual step in the block's README. Code generation (writing files programmatically) is planned for v2.
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## Roadmap
|
|
485
|
+
|
|
486
|
+
- [ ] Payments — Stripe block
|
|
487
|
+
- [ ] Payments — Lemon Squeezy block
|
|
488
|
+
- [ ] Auth — Clerk block
|
|
489
|
+
- [ ] Database — Drizzle + Supabase Postgres block
|
|
490
|
+
- [ ] Database — Mongoose + MongoDB block
|
|
491
|
+
- [ ] Code generation for layout-level injections
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## License
|
|
496
|
+
|
|
497
|
+
MIT — free forever.
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## Author
|
|
502
|
+
|
|
503
|
+
Built by [Nikhil Sai](https://x.com/itzznikhilsai).
|
|
504
|
+
|
|
505
|
+
If this helped you ship faster, a ⭐ on GitHub goes a long way.
|