@main12/auth-login 0.1.1 → 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.
Files changed (2) hide show
  1. package/README.md +187 -151
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,218 +1,254 @@
1
- # Payload Plugin Template
1
+ # @main12/auth-login
2
2
 
3
- A template repo to create a [Payload CMS](https://payloadcms.com) plugin.
3
+ **Payload CMS authentication plugin** — login, signup, OTP, forgot password, branded emails, and "Powered by Main 12" footer. Install once, configure your project name and logo, done.
4
4
 
5
- Payload is built with a robust infrastructure intended to support Plugins with ease. This provides a simple, modular, and reusable way for developers to extend the core capabilities of Payload.
6
-
7
- To build your own Payload plugin, all you need is:
5
+ ```ts
6
+ // payload.config.ts
7
+ import { authLoginPlugin } from '@main12/auth-login'
8
8
 
9
- - An understanding of the basic Payload concepts
10
- - And some JavaScript/Typescript experience
9
+ plugins: [
10
+ authLoginPlugin({
11
+ projectName: 'My SaaS',
12
+ domain: 'https://myapp.com',
13
+ style: 'hero-ui', // 'tailwind' (default) | 'hero-ui'
14
+ }),
15
+ ]
16
+ ```
11
17
 
12
- ## Background
18
+ ---
13
19
 
14
- Here is a short recap on how to integrate plugins with Payload, to learn more visit the [plugin overview page](https://payloadcms.com/docs/plugins/overview).
20
+ ## Features
15
21
 
16
- ### How to install a plugin
22
+ - **5 auth pages** — login (multi-step), signup, forgot password, verify OTP, set password
23
+ - **Multi-style** — `tailwind` (zero UI deps) or `hero-ui` (HeroUI + framer-motion). Set once in config
24
+ - **5 API endpoints** — `check-email`, `otp/send`, `otp/verify`, `set-password`, `signup`
25
+ - **OTP engine** — SHA-256 hashing + `timingSafeEqual` comparison, 10-min expiry, 3 attempts
26
+ - **Email templates** — welcome, OTP login, password reset, password changed (EN/ES)
27
+ - **Powered by Main 12** — bundled inline SVG, linked to main12.com by default
28
+ - **Zero runtime deps** (Tailwind mode) — Next.js + React are peer dependencies
17
29
 
18
- To install any plugin, simply add it to your payload.config() in the Plugin array.
30
+ ---
19
31
 
20
- ```ts
21
- import myPlugin from 'my-plugin'
32
+ ## Installation
22
33
 
23
- export const config = buildConfig({
24
- plugins: [
25
- // You can pass options to the plugin
26
- myPlugin({
27
- enabled: true,
28
- }),
29
- ],
30
- })
34
+ ```bash
35
+ pnpm add @main12/auth-login
31
36
  ```
32
37
 
33
- ### Initialization
34
-
35
- The initialization process goes in the following order:
38
+ ### Tailwind mode (default, zero UI deps)
36
39
 
37
- 1. Incoming config is validated
38
- 2. **Plugins execute**
39
- 3. Default options are integrated
40
- 4. Sanitization cleans and validates data
41
- 5. Final config gets initialized
40
+ No extra dependencies needed.
42
41
 
43
- ## Building the Plugin
42
+ ### HeroUI mode
44
43
 
45
- When you build a plugin, you are purely building a feature for your project and then abstracting it outside of the project.
44
+ ```bash
45
+ pnpm add @heroui/react framer-motion @iconify/react
46
+ ```
46
47
 
47
- ### Template Files
48
+ ---
48
49
 
49
- In the Payload [plugin template](https://github.com/payloadcms/payload/tree/main/templates/plugin), you will see a common file structure that is used across all plugins:
50
+ ## Quick Start
50
51
 
51
- 1. root folder
52
- 2. /src folder
53
- 3. /dev folder
52
+ ### 1. Add the plugin to your Payload config
54
53
 
55
- #### Root
54
+ ```ts
55
+ import { authLoginPlugin } from '@main12/auth-login'
56
56
 
57
- In the root folder, you will see various files that relate to the configuration of the plugin. We set up our environment in a similar manner in Payload core and across other projects, so hopefully these will look familiar:
57
+ export default buildConfig({
58
+ plugins: [
59
+ authLoginPlugin({
60
+ projectName: 'My App',
61
+ domain: 'https://myapp.com',
62
+ contactEmail: 'support@myapp.com',
63
+ style: 'tailwind', // or 'hero-ui'
64
+ }),
65
+ ],
66
+ // ... rest of your config
67
+ })
68
+ ```
58
69
 
59
- - **README**.md\* - This contains instructions on how to use the template. When you are ready, update this to contain instructions on how to use your Plugin.
60
- - **package**.json\* - Contains necessary scripts and dependencies. Overwrite the metadata in this file to describe your Plugin.
61
- - .**eslint**.config.js - Eslint configuration for reporting on problematic patterns.
62
- - .**gitignore** - List specific untracked files to omit from Git.
63
- - .**prettierrc**.json - Configuration for Prettier code formatting.
64
- - **tsconfig**.json - Configures the compiler options for TypeScript
65
- - .**swcrc** - Configuration for SWC, a fast compiler that transpiles and bundles TypeScript.
66
- - **vitest**.config.js - Config file for Vitest, defining how tests are run and how modules are resolved
70
+ ### 2. Add auth pages to your app
67
71
 
68
- **IMPORTANT\***: You will need to modify these files.
72
+ Create one-line route files under `src/app/(frontend)/(auth)/`:
69
73
 
70
- #### Dev
74
+ ```tsx
75
+ // login/page.tsx
76
+ export { LoginPage as default } from '@main12/auth-login/client'
71
77
 
72
- In the dev folder, you’ll find a basic payload project, created with `npx create-payload-app` and the blank template.
78
+ // signup/page.tsx
79
+ export { SignupPage as default } from '@main12/auth-login/client'
73
80
 
74
- **IMPORTANT**: Make a copy of the `.env.example` file and rename it to `.env`. Update the `DATABASE_URL` to match the database you are using and your plugin name. Update `PAYLOAD_SECRET` to a unique string.
75
- **You will not be able to run `pnpm/yarn dev` until you have created this `.env` file.**
81
+ // forgot-password/page.tsx
82
+ export { ForgotPasswordPage as default } from '@main12/auth-login/client'
76
83
 
77
- `myPlugin` has already been added to the `payload.config()` file in this project.
84
+ // verify-otp/page.tsx
85
+ export { VerifyOtpPage as default } from '@main12/auth-login/client'
78
86
 
79
- ```ts
80
- plugins: [
81
- myPlugin({
82
- collections: {
83
- posts: true,
84
- },
85
- }),
86
- ]
87
+ // set-password/page.tsx
88
+ export { SetPasswordPage as default } from '@main12/auth-login/client'
87
89
  ```
88
90
 
89
- Later when you rename the plugin or add additional options, **make sure to update it here**.
91
+ ### 3. Wire up the login action
92
+
93
+ The plugin needs a `login` function. Pass yours from Payload's `useAuth()`:
94
+
95
+ ```tsx
96
+ // login/page.tsx
97
+ 'use client'
98
+ import { LoginPage } from '@main12/auth-login/client'
99
+ import { useAuth } from '@/providers/Auth'
100
+ import AppLogo from '@/components/Logo/AppLogo'
101
+
102
+ export default function Page() {
103
+ const { login } = useAuth()
104
+ return (
105
+ <LoginPage
106
+ logo={<AppLogo width={180} height={42} />}
107
+ onPasswordLogin={login}
108
+ redirectTo="/dashboard"
109
+ poweredBy={{ enabled: true }}
110
+ />
111
+ )
112
+ }
113
+ ```
90
114
 
91
- You may wish to add collections or expand the test project depending on the purpose of your plugin. Just make sure to keep this dev environment as simplified as possible - users should be able to install your plugin without additional configuration required.
115
+ ---
92
116
 
93
- When you’re ready to start development, initiate the project with `pnpm/npm/yarn dev` and pull up [http://localhost:3000](http://localhost:3000) in your browser.
117
+ ## Configuration Options
94
118
 
95
- #### Src
119
+ ```ts
120
+ authLoginPlugin({
121
+ // === Branding ===
122
+ projectName: 'My App', // Used in email subjects and footers
123
+ contactEmail: 'hi@myapp.com', // Email footer contact
124
+ domain: 'https://myapp.com', // Links in emails
96
125
 
97
- Now that we have our environment setup and we have a dev project ready to - it’s time to build the plugin!
126
+ // === Style ===
127
+ style: 'tailwind', // 'tailwind' | 'hero-ui'
98
128
 
99
- **index.ts**
129
+ // === Enable/Disable ===
130
+ enabled: true, // Set false to disable the plugin
131
+ })
132
+ ```
100
133
 
101
- The essence of a Payload plugin is simply to extend the payload config - and that is exactly what we are doing in this file.
134
+ Each page component also accepts these props:
102
135
 
103
136
  ```ts
104
- export const myPlugin =
105
- (pluginOptions: MyPluginConfig) =>
106
- (config: Config): Config => {
107
- // do cool stuff with the config here
108
-
109
- return config
110
- }
137
+ <LoginPage
138
+ logo={...} // React node — your brand logo
139
+ onPasswordLogin={login} // Required — Payload's login function
140
+ redirectTo="/dashboard" // Where to go after login
141
+ showGoogleOAuth={true} // Show "Continue with Google" button
142
+ signupUrl="/signup" // Link to signup page
143
+ poweredBy={{ // Powered by logo config
144
+ enabled: true,
145
+ logoUrl: '/custom-logo.png', // Override the default Main12 logo
146
+ linkUrl: 'https://your-site.com',
147
+ width: 28,
148
+ height: 28,
149
+ }}
150
+ />
111
151
  ```
112
152
 
113
- First, we receive the existing payload config along with any plugin options.
114
-
115
- From here, you can extend the config as you wish.
153
+ ---
116
154
 
117
- Finally, you return the config and that is it!
155
+ ## Using Hooks & Services Directly
118
156
 
119
- ##### Spread Syntax
157
+ Don't want the pre-built pages? Use the hooks and services to build your own:
120
158
 
121
- Spread syntax (or the spread operator) is a feature in JavaScript that uses the dot notation **(...)** to spread elements from arrays, strings, or objects into various contexts.
159
+ ```tsx
160
+ import { useLoginFlow, useVerifyOtpFlow, checkEmail, sendOtp } from '@main12/auth-login/client'
122
161
 
123
- We are going to use spread syntax to allow us to add data to existing arrays without losing the existing data. It is crucial to spread the existing data correctly – else this can cause adverse behavior and conflicts with Payload config and other plugins.
124
-
125
- Let’s say you want to build a plugin that adds a new collection:
126
-
127
- ```ts
128
- config.collections = [
129
- ...(config.collections || []),
130
- // Add additional collections here
131
- ]
162
+ function MyCustomLogin() {
163
+ const { email, handleEmailSubmit, ... } = useLoginFlow({
164
+ redirectTo: '/dashboard',
165
+ onPasswordLogin: login,
166
+ })
167
+ // Build your own UI with these values
168
+ }
132
169
  ```
133
170
 
134
- First we spread the `config.collections` to ensure that we don’t lose the existing collections, then you can add any additional collections just as you would in a regular payload config.
171
+ ### Exported Hooks
135
172
 
136
- This same logic is applied to other properties like admin, hooks, globals:
173
+ | Hook | Purpose |
174
+ |------|---------|
175
+ | `useLoginFlow` | Multi-step login state machine (email → password/OTP) |
176
+ | `useVerifyOtpFlow` | OTP input, verify, resend with cooldown |
177
+ | `useForgotPasswordFlow` | Email → check → send OTP |
178
+ | `useSetPasswordFlow` | Set password with strength indicator |
137
179
 
138
- ```ts
139
- config.globals = [
140
- ...(config.globals || []),
141
- // Add additional globals here
142
- ]
180
+ ### Exported Services
143
181
 
144
- config.hooks = {
145
- ...(incomingConfig.hooks || {}),
146
- // Add additional hooks here
147
- }
148
- ```
182
+ | Function | Description |
183
+ |----------|-------------|
184
+ | `checkEmail(email)` | Check if user exists and has password |
185
+ | `sendOtp(email, purpose)` | Send OTP to email |
186
+ | `verifyOtp(email, otp)` | Verify OTP code |
187
+ | `setUserPassword(password, confirm)` | Set/update password |
188
+ | `signup(name, email)` | Create new user |
189
+ | `initiateGoogleLogin(redirect)` | Redirect to Google OAuth |
149
190
 
150
- Some properties will be slightly different to extend, for instance the onInit property:
191
+ ---
151
192
 
152
- ```ts
153
- import { onInitExtension } from './onInitExtension' // example file
193
+ ## API Endpoints
154
194
 
155
- config.onInit = async (payload) => {
156
- if (incomingConfig.onInit) await incomingConfig.onInit(payload)
157
- // Add additional onInit code by defining an onInitExtension function
158
- onInitExtension(pluginOptions, payload)
159
- }
160
- ```
195
+ Registered automatically by the plugin:
161
196
 
162
- If you wish to add to the onInit, you must include the **async/await**. We don’t use spread syntax in this case, instead you must await the existing `onInit` before running additional functionality.
197
+ | Method | Path | Description |
198
+ |--------|------|-------------|
199
+ | POST | `/api/auth/check-email` | Check if email is registered |
200
+ | POST | `/api/auth/otp/send` | Generate + send OTP |
201
+ | POST | `/api/auth/otp/verify` | Verify OTP + login |
202
+ | POST | `/api/auth/set-password` | Set/update password |
203
+ | POST | `/api/auth/signup` | Create account |
163
204
 
164
- In the template, we have stubbed out some addition `onInit` actions that seeds in a document to the `plugin-collection`, you can use this as a base point to add more actions - and if not needed, feel free to delete it.
205
+ ---
165
206
 
166
- ##### Types.ts
207
+ ## Email Templates
167
208
 
168
- If your plugin has options, you should define and provide types for these options.
209
+ Four HTML email templates in EN/ES, using the host project's Payload email adapter:
169
210
 
170
- ```ts
171
- export type MyPluginConfig = {
172
- /**
173
- * List of collections to add a custom field
174
- */
175
- collections?: Partial<Record<CollectionSlug, true>>
176
- /**
177
- * Disable the plugin
178
- */
179
- disabled?: boolean
180
- }
181
- ```
211
+ - **Welcome** — sent on signup
212
+ - **OTP** — 6-digit code for login or password reset
213
+ - **Password Reset** — OTP email for forgot password flow
214
+ - **Password Changed** — confirmation after password update
182
215
 
183
- If possible, include JSDoc comments to describe the options and their types. This allows a developer to see details about the options in their editor.
216
+ Override translations or template functions via the `emails` option (Phase 2).
184
217
 
185
- ##### Testing
218
+ ---
186
219
 
187
- Having a test suite for your plugin is essential to ensure quality and stability. **Vitest** is a fast, modern testing framework that works seamlessly with Vite and supports TypeScript out of the box.
220
+ ## Dev Testing
188
221
 
189
- Vitest organizes tests into test suites and cases, similar to other testing frameworks. We recommend creating individual tests based on the expected behavior of your plugin from start to finish.
222
+ This repo ships with a dev harness. To test locally:
190
223
 
191
- Writing tests with Vitest is very straightforward, and you can learn more about how it works in the [Vitest documentation.](https://vitest.dev/)
224
+ ```bash
225
+ cd auth-login-plugin
226
+ pnpm install
227
+ pnpm dev
228
+ ```
192
229
 
193
- For this template, we stubbed out `int.spec.ts` in the `dev` folder where you can write your tests.
230
+ Visits:
231
+ - `http://localhost:3000/login` — multi-step login
232
+ - `http://localhost:3000/signup` — create account
233
+ - `http://localhost:3000/forgot-password` — password reset
234
+ - `http://localhost:3000/admin` — Payload admin panel
194
235
 
195
- ```ts
196
- describe('Plugin tests', () => {
197
- // Create tests to ensure expected behavior from the plugin
198
- it('some condition that must be met', () => {
199
- // Write your test logic here
200
- expect(...)
201
- })
202
- })
203
- ```
236
+ The dev config uses SQLite (no external DB needed) with a Users collection pre-configured.
237
+
238
+ ---
204
239
 
205
- ## Best practices
240
+ ## Requirements
206
241
 
207
- With this tutorial and the plugin template, you should have everything you need to start building your own plugin.
208
- In addition to the setup, here are other best practices aim we follow:
242
+ | Dependency | Version | Required |
243
+ |------------|---------|----------|
244
+ | Payload CMS | `^3.82.0` | ✅ |
245
+ | Next.js | `^16.0.0` | ✅ |
246
+ | React | `^19.0.0` | ✅ |
247
+ | HeroUI | `^2.x` | Only for `style: 'hero-ui'` |
248
+ | Framer Motion | `^12.x` | Only for `style: 'hero-ui'` |
209
249
 
210
- - **Providing an enable / disable option:** For a better user experience, provide a way to disable the plugin without uninstalling it. This is especially important if your plugin adds additional webpack aliases, this will allow you to still let the webpack run to prevent errors.
211
- - **Include tests in your GitHub CI workflow**: If you’ve configured tests for your package, integrate them into your workflow to run the tests each time you commit to the plugin repository. Learn more about [how to configure tests into your GitHub CI workflow.](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs)
212
- - **Publish your finished plugin to NPM**: The best way to share and allow others to use your plugin once it is complete is to publish an NPM package. This process is straightforward and well documented, find out more [creating and publishing a NPM package here.](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/).
213
- - **Add payload-plugin topic tag**: Apply the tag **payload-plugin **to your GitHub repository. This will boost the visibility of your plugin and ensure it gets listed with [existing payload plugins](https://github.com/topics/payload-plugin).
214
- - **Use [Semantic Versioning](https://semver.org/) (SemVar)** - With the SemVar system you release version numbers that reflect the nature of changes (major, minor, patch). Ensure all major versions reference their Payload compatibility.
250
+ ---
215
251
 
216
- # Questions
252
+ ## License
217
253
 
218
- Please contact [Payload](mailto:dev@payloadcms.com) with any questions about using this plugin template.
254
+ MIT © Main 12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@main12/auth-login",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Reusable Payload CMS auth plugin — login, signup, OTP, forgot password, branded emails, Powered by Main12",
5
5
  "license": "MIT",
6
6
  "type": "module",