umpordez 1.0.0 → 1.0.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/.claude/settings.local.json +5 -1
- package/README.md +123 -0
- package/package.json +1 -1
- package/template/README.md +128 -0
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
"Bash(echo:*)",
|
|
11
11
|
"WebFetch(domain:umpordez.com)",
|
|
12
12
|
"Bash(curl:*)",
|
|
13
|
-
"Bash(python3:*)"
|
|
13
|
+
"Bash(python3:*)",
|
|
14
|
+
"WebFetch(domain:github.com)",
|
|
15
|
+
"WebFetch(domain:raw.githubusercontent.com)",
|
|
16
|
+
"Bash(gh api:*)",
|
|
17
|
+
"WebFetch(domain:api.github.com)"
|
|
14
18
|
]
|
|
15
19
|
}
|
|
16
20
|
}
|
package/README.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# umpordez
|
|
2
|
+
|
|
3
|
+
SaaS starter kit generator.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Why?
|
|
8
|
+
|
|
9
|
+
We all know the drill; you want to build a SaaS, you spend two weeks
|
|
10
|
+
setting up auth, multi-tenancy, file uploads, admin panels, role-based
|
|
11
|
+
access... and then you still haven't written a single line of your
|
|
12
|
+
actual product.
|
|
13
|
+
|
|
14
|
+
I've built this same architecture across multiple production apps
|
|
15
|
+
(different domains, same bones). At some point I got tired of
|
|
16
|
+
copying between repos, adapting folder names, and forgetting to
|
|
17
|
+
update that one hardcoded port somewhere.
|
|
18
|
+
|
|
19
|
+
So I made a CLI that generates the whole thing. One command, answer a
|
|
20
|
+
few questions, and you get a production-ready multi-tenant SaaS with
|
|
21
|
+
everything wired up.
|
|
22
|
+
|
|
23
|
+
**No magic, no hidden abstractions.** The generated code is yours;
|
|
24
|
+
plain TypeScript, plain React, plain SQL. Read it, change it, own it.
|
|
25
|
+
|
|
26
|
+
## What you get
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
server/
|
|
30
|
+
apps/api/ Admin API (Express + TypeScript)
|
|
31
|
+
apps/site-api/ Public API (Express + TypeScript)
|
|
32
|
+
apps/shared/ Shared middlewares + utilities
|
|
33
|
+
core/ Models, DB, S3, email, auth
|
|
34
|
+
console/ Task runner (migrations, seeds, custom tasks)
|
|
35
|
+
migrations/ Raw SQL migrations (Knex)
|
|
36
|
+
|
|
37
|
+
ui/admin/ React SPA (Vite + shadcn/ui + Tailwind)
|
|
38
|
+
ui/site/ Public site (Express + EJS + Tailwind)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The architecture:
|
|
42
|
+
|
|
43
|
+
- **Multi-tenant**; users > accounts with role-based access
|
|
44
|
+
(admin, owner, manager, user)
|
|
45
|
+
- **Multi-API**; separate Express servers sharing core logic,
|
|
46
|
+
add more as you need
|
|
47
|
+
- **Cookie auth**; httpOnly JWT, 30-day expiry, no tokens
|
|
48
|
+
in localStorage
|
|
49
|
+
- **S3 uploads**; multer-s3 with signed URLs (never public-read)
|
|
50
|
+
- **Context DI**; fresh context per request with all models
|
|
51
|
+
instantiated, no singletons
|
|
52
|
+
- **PostgreSQL**; Knex.js with raw SQL migrations, because ORMs
|
|
53
|
+
lie to you eventually :X
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g umpordez
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
### Create a project
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
umpordez
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
That's it. It asks you a few questions (name, domain, ports, colors)
|
|
70
|
+
and generates everything. Then:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
cd my-project
|
|
74
|
+
./install.sh # install deps
|
|
75
|
+
./seed.sh # create db + migrate + seed admin
|
|
76
|
+
./dev.sh # start all services
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Build for production
|
|
80
|
+
|
|
81
|
+
The build system is split in two steps on purpose; compilation is
|
|
82
|
+
expensive and should run on your machine, dependency installation
|
|
83
|
+
needs to happen on the target machine (native bindings, OS-specific
|
|
84
|
+
stuff).
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Step 1: compile locally, push artifacts to builds repo
|
|
88
|
+
umpordez build ../app ../builds
|
|
89
|
+
|
|
90
|
+
# Step 2: on prod/staging, install production deps
|
|
91
|
+
umpordez build-deps ../builds
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
After `build-deps`, the builds repo is ready to clone and run. Add
|
|
95
|
+
your `.env`, start the services, done.
|
|
96
|
+
|
|
97
|
+
### Other commands
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
umpordez --help # see all commands
|
|
101
|
+
umpordez --version # check version
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Tech stack
|
|
105
|
+
|
|
106
|
+
| Layer | Tech |
|
|
107
|
+
|------------|------|
|
|
108
|
+
| Backend | TypeScript, Express, PostgreSQL, Knex.js, Zod |
|
|
109
|
+
| Admin UI | React 18, Vite, Tailwind, shadcn/ui (Radix), React Query v5 |
|
|
110
|
+
| Public site| Express + EJS + Tailwind |
|
|
111
|
+
| Auth | httpOnly JWT cookies (bcrypt + 30-day expiry) |
|
|
112
|
+
| Uploads | AWS S3 via multer-s3, signed URLs |
|
|
113
|
+
| Email | Nodemailer + HTML templates |
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
MIT; do whatever you want with it.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
*May the speedy force be with you.* ✌️
|
|
122
|
+
|
|
123
|
+
[youtube.com/ligeiro](https://youtube.com/ligeiro)
|
package/package.json
CHANGED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
{{PROJECT_DESCRIPTION}}
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
./install.sh # install all deps
|
|
11
|
+
./seed.sh # create db + migrate + seed admin user
|
|
12
|
+
./dev.sh # start everything (Ctrl+C to stop)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Admin panel: `http://localhost:{{ADMIN_UI_PORT}}`
|
|
16
|
+
Admin API: `http://localhost:{{API_PORT}}`
|
|
17
|
+
Site: `http://localhost:{{SITE_PORT}}`
|
|
18
|
+
|
|
19
|
+
## How it works
|
|
20
|
+
|
|
21
|
+
Multi-tenant SaaS; users can belong to multiple accounts with
|
|
22
|
+
different roles. Each request gets a fresh Context with all models
|
|
23
|
+
instantiated (no singletons, no global state).
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
users (global identity)
|
|
27
|
+
|
|
|
28
|
+
user_in_accounts (user_id + account_id + role)
|
|
29
|
+
|
|
|
30
|
+
accounts (tenant)
|
|
31
|
+
|
|
|
32
|
+
[your domain entities scoped by account_id]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Roles: `admin` (platform-wide), `owner`, `manager`, `user`
|
|
36
|
+
|
|
37
|
+
For the full architecture details, patterns and how-tos see
|
|
38
|
+
[architecture.md](architecture.md). For coding standards and style
|
|
39
|
+
rules see [code.md](code.md).
|
|
40
|
+
|
|
41
|
+
## Project structure
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
server/
|
|
45
|
+
apps/api/ Admin API (Express, port {{API_PORT}})
|
|
46
|
+
routes/ auth, user, account, admin, files
|
|
47
|
+
apps/site-api/ Public API (Express, port {{SITE_API_PORT}})
|
|
48
|
+
routes/ public endpoints
|
|
49
|
+
apps/shared/ Shared middlewares + buildHandler
|
|
50
|
+
core/ Business logic
|
|
51
|
+
context.ts DI container (fresh per request)
|
|
52
|
+
models/ One model per entity (extends BaseModel)
|
|
53
|
+
db.ts Knex wrapper
|
|
54
|
+
s3.ts S3 uploads + signed URLs
|
|
55
|
+
email.ts Nodemailer + HTML templates
|
|
56
|
+
errors.ts AppError hierarchy (400, 401, 403, 404, 409)
|
|
57
|
+
console/ Task runner
|
|
58
|
+
tasks/ One file per task (seed-admin, etc.)
|
|
59
|
+
migrations/ Raw SQL (Knex)
|
|
60
|
+
emails/ HTML email templates
|
|
61
|
+
|
|
62
|
+
ui/admin/ React SPA (Vite, port {{ADMIN_UI_PORT}})
|
|
63
|
+
src/
|
|
64
|
+
pages/ public/, user/, admin/, account/
|
|
65
|
+
layouts/ One layout per scope
|
|
66
|
+
components/ui/ shadcn/ui (Radix + Tailwind)
|
|
67
|
+
hooks/queries/ React Query hooks per entity
|
|
68
|
+
lib/ fetchApi, query-keys, utils
|
|
69
|
+
|
|
70
|
+
ui/site/ Public site (Express + EJS, port {{SITE_PORT}})
|
|
71
|
+
views/ EJS templates
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Commands
|
|
75
|
+
|
|
76
|
+
### Server (from `server/`)
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm run dev # admin API with hot-reload
|
|
80
|
+
npm run dev:site-api # site API with hot-reload
|
|
81
|
+
npm run build # TypeScript compilation
|
|
82
|
+
npm run migrate:latest # run pending migrations
|
|
83
|
+
npm run migrate:rollback # rollback last batch
|
|
84
|
+
npm run migrate:make NAME # create new migration
|
|
85
|
+
npm run console -- --task=TASK_NAME
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Admin UI (from `ui/admin/`)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm run dev # Vite dev server
|
|
92
|
+
npm run build # production build
|
|
93
|
+
npm run lint # ESLint
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Site (from `ui/site/`)
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npm run dev # Express + Tailwind watcher
|
|
100
|
+
npm run build # production build
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Production build
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
umpordez build ../app ../builds # compile + move artifacts
|
|
107
|
+
umpordez build-deps ../builds # install prod deps on target
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Tech stack
|
|
111
|
+
|
|
112
|
+
| What | How |
|
|
113
|
+
|-------------|-----|
|
|
114
|
+
| Backend | TypeScript, Express, PostgreSQL, Knex.js, Zod |
|
|
115
|
+
| Admin UI | React 18, Vite, Tailwind, shadcn/ui, React Query v5 |
|
|
116
|
+
| Public site | Express + EJS + Tailwind |
|
|
117
|
+
| Auth | httpOnly JWT cookies (bcrypt, 30-day expiry) |
|
|
118
|
+
| Uploads | AWS S3 via multer-s3, signed URLs |
|
|
119
|
+
| Email | Nodemailer + HTML templates |
|
|
120
|
+
|
|
121
|
+
## Docs
|
|
122
|
+
|
|
123
|
+
- [architecture.md](architecture.md) - patterns, how-tos, examples
|
|
124
|
+
- [code.md](code.md) - coding standards, naming, style rules
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
MIT
|