showpane 0.4.1 → 0.4.3
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/README.md +26 -1
- package/bundle/meta/scaffold-manifest.json +73 -0
- package/bundle/scaffold/VERSION +1 -0
- package/bundle/scaffold/__dot__env.example +24 -0
- package/bundle/scaffold/__dot__gitignore +41 -0
- package/bundle/scaffold/docker/Caddyfile +3 -0
- package/bundle/scaffold/docker/Dockerfile +30 -0
- package/bundle/scaffold/docker-compose.yml +53 -0
- package/bundle/scaffold/next.config.ts +20 -0
- package/bundle/scaffold/package-lock.json +5843 -0
- package/bundle/scaffold/package.json +42 -0
- package/bundle/scaffold/postcss.config.js +6 -0
- package/bundle/scaffold/prisma/migrations/20260408000000_init/migration.sql +143 -0
- package/bundle/scaffold/prisma/migrations/20260408010000_add_visitor_tracking/migration.sql +6 -0
- package/bundle/scaffold/prisma/migrations/20260409040000_add_portal_file_checksum/migration.sql +2 -0
- package/bundle/scaffold/prisma/migrations/migration_lock.toml +3 -0
- package/bundle/scaffold/prisma/schema.local.prisma +131 -0
- package/bundle/scaffold/prisma/schema.prisma +128 -0
- package/bundle/scaffold/prisma/seed.ts +49 -0
- package/bundle/scaffold/public/example-avatar.svg +4 -0
- package/bundle/scaffold/public/example-logo.svg +4 -0
- package/bundle/scaffold/public/robots.txt +2 -0
- package/bundle/scaffold/scripts/backup.sh +19 -0
- package/bundle/scaffold/scripts/e2e-verify.sh +487 -0
- package/bundle/scaffold/scripts/prisma-db-push.mjs +7 -0
- package/bundle/scaffold/scripts/prisma-generate.mjs +3 -0
- package/bundle/scaffold/scripts/prisma-schema.mjs +74 -0
- package/bundle/scaffold/scripts/restore.sh +31 -0
- package/bundle/scaffold/src/__tests__/client-portals.test.ts +80 -0
- package/bundle/scaffold/src/__tests__/portal-contracts.test.ts +32 -0
- package/bundle/scaffold/src/app/(portal)/client/[slug]/page.tsx +79 -0
- package/bundle/scaffold/src/app/(portal)/client/[slug]/s/[token]/route.ts +22 -0
- package/bundle/scaffold/src/app/(portal)/client/example/example-client.tsx +372 -0
- package/bundle/scaffold/src/app/(portal)/client/example/page.tsx +5 -0
- package/bundle/scaffold/src/app/(portal)/client/layout.tsx +7 -0
- package/bundle/scaffold/src/app/(portal)/client/page.tsx +18 -0
- package/bundle/scaffold/src/app/api/client-auth/route.ts +82 -0
- package/bundle/scaffold/src/app/api/client-auth/share/route.ts +30 -0
- package/bundle/scaffold/src/app/api/client-events/route.ts +87 -0
- package/bundle/scaffold/src/app/api/client-files/[...path]/route.ts +80 -0
- package/bundle/scaffold/src/app/api/client-files/client-upload/route.ts +118 -0
- package/bundle/scaffold/src/app/api/client-files/route.ts +37 -0
- package/bundle/scaffold/src/app/api/client-files/upload/route.ts +131 -0
- package/bundle/scaffold/src/app/api/health/route.ts +19 -0
- package/bundle/scaffold/src/app/globals.css +7 -0
- package/bundle/scaffold/src/app/layout.tsx +25 -0
- package/bundle/scaffold/src/app/page.tsx +177 -0
- package/bundle/scaffold/src/components/portal-login.tsx +169 -0
- package/bundle/scaffold/src/components/portal-shell.tsx +373 -0
- package/bundle/scaffold/src/lib/abuse-controls.ts +43 -0
- package/bundle/scaffold/src/lib/branding.ts +50 -0
- package/bundle/scaffold/src/lib/client-auth.ts +98 -0
- package/bundle/scaffold/src/lib/client-portals.ts +134 -0
- package/bundle/scaffold/src/lib/control-plane.ts +100 -0
- package/bundle/scaffold/src/lib/db.ts +7 -0
- package/bundle/scaffold/src/lib/files.ts +124 -0
- package/bundle/scaffold/src/lib/load-app-env.ts +42 -0
- package/bundle/scaffold/src/lib/portal-contracts.ts +69 -0
- package/bundle/scaffold/src/lib/prisma-client.ts +5 -0
- package/bundle/scaffold/src/lib/runtime-state.ts +69 -0
- package/bundle/scaffold/src/lib/storage.ts +204 -0
- package/bundle/scaffold/src/lib/token.ts +186 -0
- package/bundle/scaffold/src/lib/utils.ts +6 -0
- package/bundle/scaffold/src/middleware.ts +61 -0
- package/bundle/scaffold/tailwind.config.ts +15 -0
- package/bundle/scaffold/tests/__dot__gitkeep +0 -0
- package/bundle/scaffold/tsconfig.json +23 -0
- package/bundle/scaffold/vitest.config.ts +13 -0
- package/bundle/toolchain/VERSION +1 -0
- package/bundle/toolchain/bin/check-slug.ts +59 -0
- package/bundle/toolchain/bin/create-deploy-bundle.ts +93 -0
- package/bundle/toolchain/bin/create-portal.ts +71 -0
- package/bundle/toolchain/bin/delete-portal.ts +48 -0
- package/bundle/toolchain/bin/export-file-manifest.ts +84 -0
- package/bundle/toolchain/bin/export-runtime-state.ts +90 -0
- package/bundle/toolchain/bin/generate-share-link.ts +68 -0
- package/bundle/toolchain/bin/list-portals.ts +53 -0
- package/bundle/toolchain/bin/materialize-file.ts +35 -0
- package/bundle/toolchain/bin/query-analytics.ts +88 -0
- package/bundle/toolchain/bin/rotate-credentials.ts +57 -0
- package/bundle/toolchain/bin/showpane-config +63 -0
- package/bundle/toolchain/bin/tsconfig.json +13 -0
- package/bundle/toolchain/skills/VERSION +1 -0
- package/bundle/toolchain/skills/portal-analytics/SKILL.md +263 -0
- package/bundle/toolchain/skills/portal-create/SKILL.md +341 -0
- package/bundle/toolchain/skills/portal-credentials/SKILL.md +274 -0
- package/bundle/toolchain/skills/portal-delete/SKILL.md +265 -0
- package/bundle/toolchain/skills/portal-deploy/SKILL.md +721 -0
- package/bundle/toolchain/skills/portal-dev/SKILL.md +301 -0
- package/bundle/toolchain/skills/portal-list/SKILL.md +253 -0
- package/bundle/toolchain/skills/portal-onboard/SKILL.md +277 -0
- package/bundle/toolchain/skills/portal-preview/SKILL.md +257 -0
- package/bundle/toolchain/skills/portal-setup/SKILL.md +309 -0
- package/bundle/toolchain/skills/portal-share/SKILL.md +234 -0
- package/bundle/toolchain/skills/portal-status/SKILL.md +268 -0
- package/bundle/toolchain/skills/portal-update/SKILL.md +348 -0
- package/bundle/toolchain/skills/portal-upgrade/SKILL.md +235 -0
- package/bundle/toolchain/skills/portal-verify/SKILL.md +265 -0
- package/bundle/toolchain/skills/shared/bin/check-portal-guard.sh +49 -0
- package/bundle/toolchain/skills/shared/platform-constraints.md +33 -0
- package/bundle/toolchain/skills/shared/preamble.md +137 -0
- package/bundle/toolchain/templates/consulting/consulting-client.tsx +205 -0
- package/bundle/toolchain/templates/onboarding/onboarding-client.tsx +237 -0
- package/bundle/toolchain/templates/sales-followup/sales-followup-client.tsx +283 -0
- package/dist/index.js +1248 -164
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -11,12 +11,37 @@ npx showpane
|
|
|
11
11
|
## Commands
|
|
12
12
|
|
|
13
13
|
### `npx showpane` (default)
|
|
14
|
-
Scaffold a new Showpane portal project.
|
|
14
|
+
Scaffold a new Showpane portal project. Unpacks a version-pinned scaffold, installs the global Showpane toolchain, sets up Prisma, and starts the local app.
|
|
15
|
+
|
|
16
|
+
Flags:
|
|
17
|
+
|
|
18
|
+
- `--name <company>` — provide the company name non-interactively
|
|
19
|
+
- `--yes` — skip prompts when paired with `--name`
|
|
20
|
+
- `--no-open` — do not open the local app in the browser
|
|
21
|
+
- `--verbose` — stream raw install logs instead of the quiet installer view
|
|
15
22
|
|
|
16
23
|
### `showpane login`
|
|
17
24
|
Authenticate with Showpane Cloud for hosted portal deployment.
|
|
18
25
|
This is auth only — org creation and billing happen in the Showpane Cloud web app.
|
|
19
26
|
|
|
27
|
+
### `showpane claude`
|
|
28
|
+
Resume your Showpane workspace by launching Claude Code in the right project directory.
|
|
29
|
+
|
|
30
|
+
Flags:
|
|
31
|
+
|
|
32
|
+
- `--project <name-or-path>` — open a specific remembered workspace
|
|
33
|
+
- `--yes` / `--name <company>` — only used when no workspace exists yet and Showpane needs to create the first one
|
|
34
|
+
- `--verbose` — show raw setup logs during first-time onboarding
|
|
35
|
+
|
|
36
|
+
### `showpane projects`
|
|
37
|
+
List remembered Showpane workspaces and show which one is currently active for global skills.
|
|
38
|
+
|
|
39
|
+
### `showpane sync`
|
|
40
|
+
Install or refresh the global Showpane toolchain and Claude Code skills for the current CLI version.
|
|
41
|
+
|
|
42
|
+
### `showpane upgrade`
|
|
43
|
+
Upgrade a generated Showpane project using packaged scaffold assets instead of upstream git history.
|
|
44
|
+
|
|
20
45
|
## Requirements
|
|
21
46
|
|
|
22
47
|
- Node.js 20+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"generatedAt": "2026-04-09T11:52:07.132Z",
|
|
4
|
+
"scaffoldVersion": "0.2.0",
|
|
5
|
+
"files": {
|
|
6
|
+
".env.example": "0dd692f1c7e6bcabdf5dbdfe9abb73797d79d8e90da150d6098b63ddc695dc29",
|
|
7
|
+
".gitignore": "998e5f43865ea56ac79a05acfd5d4b0d696f310bd5325a1ed458c3d40154d437",
|
|
8
|
+
"VERSION": "1f930dd1f133c1f97a94fe3acb8db34372cf4c01ffdb2b3ff4ca72f9494121e9",
|
|
9
|
+
"docker-compose.yml": "420fd123da019c22f03662933537e24779b4c2c91f90c23abfec5965cd0f35ce",
|
|
10
|
+
"docker/Caddyfile": "d9c58086986795f5b3e42ff9b5942e60b8df946a1a0c40351381616c0b4d2bed",
|
|
11
|
+
"docker/Dockerfile": "340470e3735ea53b2c03003a13a91361652291add33c40a2bf13e6af2a8cb73a",
|
|
12
|
+
"next.config.ts": "cf27999cc274cce79bc4c8df11789807719abf40752b60e4b4967a3d2f0ed013",
|
|
13
|
+
"package-lock.json": "d8e30eb86f08e70787d4459a084b4ab2a9f119696bbd3146ec4ba5675fffd3c2",
|
|
14
|
+
"package.json": "f5ee82c0447ee17c3bd4094f8c5c83b6d7f173b407458908d453e94664e6f41b",
|
|
15
|
+
"postcss.config.js": "fa650b380adfabb151a0b352f7135e107e6352345f899060f1c5c231228f94bf",
|
|
16
|
+
"prisma/migrations/20260408000000_init/migration.sql": "a637c252920b45c7dd3e8225c939da373bbaeeccc6f208f9e52c3ff0133a3438",
|
|
17
|
+
"prisma/migrations/20260408010000_add_visitor_tracking/migration.sql": "a4432b5d037f069e97ed1765a5bf5a4f3b502e29af1a05406b2aa42bde735e28",
|
|
18
|
+
"prisma/migrations/20260409040000_add_portal_file_checksum/migration.sql": "bbfad517dea1257f40e5a0d7807677452fb893a34afbc6d81a3d2bbabc5932af",
|
|
19
|
+
"prisma/migrations/migration_lock.toml": "99836963713b4f5b269ad49af0ed3d7b0b2e336115c2f92dc9ac683d139d0900",
|
|
20
|
+
"prisma/schema.local.prisma": "4b36b52ef0ccfd5980f05ab97e821001a0f4bb658f13d693a6e3422233399eb8",
|
|
21
|
+
"prisma/schema.prisma": "904e517e8956e1b61534d18db6a27c104008ec1d57d474e22e67946c9a1f60ca",
|
|
22
|
+
"prisma/seed.ts": "1dea3de4b36263e6172817508e113ba416fbcd8caff80bc190f35cd3b4b3e2c5",
|
|
23
|
+
"public/example-avatar.svg": "0edeb0d3fbefa89cc27ffe6564d20e3ee0fd073cb6d9f2a025248ef3b3f277fd",
|
|
24
|
+
"public/example-logo.svg": "bc5cd933aff2a17698dee66a7b4ea940ad12238e9d813474d643b459b1e8d6da",
|
|
25
|
+
"public/robots.txt": "331ea9090db0c9f6f597bd9840fd5b171830f6e0b3ba1cb24dfa91f0c95aedc1",
|
|
26
|
+
"scripts/backup.sh": "7d94758c5f1b0d3a722ec8a1a0b819f1a5f480b762790cf4eeccdd6fda46d11b",
|
|
27
|
+
"scripts/e2e-verify.sh": "48c5983b8f2facc228bb4ea1ac0998064268f0fdb0088208dcb12bb1e48c3244",
|
|
28
|
+
"scripts/prisma-db-push.mjs": "76ac85fe65b5dc3d9cc7432e44618fcc84b7443574c8d88198d01f13ac23c040",
|
|
29
|
+
"scripts/prisma-generate.mjs": "d371e63388fa39f963b7c3c7cb8f87e0d9cd43cbf69d254b999108e29b8738c8",
|
|
30
|
+
"scripts/prisma-schema.mjs": "4c502f640a24558b8000613a06cc956b2253849e3cd8e71849a48db9a94ed435",
|
|
31
|
+
"scripts/restore.sh": "4c1be4f0d19aa4572842981e818684349dacbb4ae319ad75ef2b03ee63f0cf98",
|
|
32
|
+
"src/__tests__/client-portals.test.ts": "c6999300e9289333c72cc4493dd13a2b344794839ee76232fc9ebdd08f021b89",
|
|
33
|
+
"src/__tests__/portal-contracts.test.ts": "80066377d3281786c2bb9ecc857514124e094a2e66dca2fb08ded994c25fa2bc",
|
|
34
|
+
"src/app/(portal)/client/[slug]/page.tsx": "4f2f9253b2ad5d37a0f13759db52c786ae9c401f50fae9431da1417e9736e000",
|
|
35
|
+
"src/app/(portal)/client/[slug]/s/[token]/route.ts": "a445e54b9139e40dfe0bc039e34e6af224a27f75a614741ab224d317ad4d3ec9",
|
|
36
|
+
"src/app/(portal)/client/example/example-client.tsx": "b9b744f0358b7773f319757157598fc69059eb38e0eaa1c09cb5fc10cfc3894b",
|
|
37
|
+
"src/app/(portal)/client/example/page.tsx": "f330864f63c9feea76c8a62c3eba3ce57578627e0d4abd929fd7fefdfc7af058",
|
|
38
|
+
"src/app/(portal)/client/layout.tsx": "4f43871510408a81da229d48ae316ec1d1c1beda93121922246300a2c8fd0999",
|
|
39
|
+
"src/app/(portal)/client/page.tsx": "af36f1a6f359d6a7bd4a6ac550058c9d9c107e9885bb238b4c06ec26700e23e3",
|
|
40
|
+
"src/app/api/client-auth/route.ts": "46508351fce1902c1878efce86b5d4ebdd28a4977941100fdc77a48d79c5d765",
|
|
41
|
+
"src/app/api/client-auth/share/route.ts": "ed82414212dcd26af8c6c0f2bd44d9d79a727ed35cfedbac8c4077a6220aad14",
|
|
42
|
+
"src/app/api/client-events/route.ts": "13d545537b7e8ce421e6169d25c105adf2a2de3d978ae0a2c6751ff5f7d2eb33",
|
|
43
|
+
"src/app/api/client-files/[...path]/route.ts": "d6279a8eab48aa82d07ac8d467276968898c0d426eeec0a7d1fba1fa754ef405",
|
|
44
|
+
"src/app/api/client-files/client-upload/route.ts": "c0b63a4b0e84093e0eaee4d8e0b06ee7281daa72279a455e56c56985e404a9cf",
|
|
45
|
+
"src/app/api/client-files/route.ts": "b8897673fd7578d3c2ad3b7f78ccd64f99413eb4181f82b90009913377dadbdb",
|
|
46
|
+
"src/app/api/client-files/upload/route.ts": "70e97bccd950953106261da1daa0381ac72778113129b718cf87d1078ca77b5f",
|
|
47
|
+
"src/app/api/health/route.ts": "78fff55707372ce0cd6e9e49ef4f049622bc43cc42916d3f83e0162409d678b1",
|
|
48
|
+
"src/app/globals.css": "28dcda76006d0e6af01b6dcf1a315dc5b5b6931c880fc53fd6565ff09d5dd13a",
|
|
49
|
+
"src/app/layout.tsx": "c17aabeb2b486f023e777230343ace6cc06840f641a10b9dd9f65e092018f82f",
|
|
50
|
+
"src/app/page.tsx": "a0778e98016957ce4ccdb58fae9be0a4a71e1961fd39a2dfca1612914179b1ae",
|
|
51
|
+
"src/components/portal-login.tsx": "8b0d91bb28674e1102fd2e5b5ddcc3a93755dd806fbd3d1b2dbea2646cffca5e",
|
|
52
|
+
"src/components/portal-shell.tsx": "a4e16e118ef93f79e71fb69e80f1fac6e6fff90f0fbdacdf8deb821a57656877",
|
|
53
|
+
"src/lib/abuse-controls.ts": "d79d58d93267aca48ad0b7b9b91f753c9a3c27263e4e98daf768a950c44a6fc6",
|
|
54
|
+
"src/lib/branding.ts": "cc55f40e02bc3e486b227988f95739ca1cda8012c97b591295995eb4465efd57",
|
|
55
|
+
"src/lib/client-auth.ts": "b9bdfe77dbe5d6ec6c6a930627fc43d3253f0d76fd8fc4093af5a75742bebe42",
|
|
56
|
+
"src/lib/client-portals.ts": "0a2c1ed8890bee35cd5f582554ede7da8a51466aec052395e44810198e6d48e2",
|
|
57
|
+
"src/lib/control-plane.ts": "e0cf39f28ec7de715fd5cfbb5f4240773fcd3d775cd1677588dd749fff740a0e",
|
|
58
|
+
"src/lib/db.ts": "65fb87fde5a05fa033234f3a976f6730d99fab7982a83821c792d09fc659e439",
|
|
59
|
+
"src/lib/files.ts": "24fd8d1d53c180d62441019395fb140ba3baa28311918ac488284adcdda8eb9a",
|
|
60
|
+
"src/lib/load-app-env.ts": "78b80e17d896885f0d72315ee9a6cf7a0a8c6c08171f26e3d599bb9b2e8afeee",
|
|
61
|
+
"src/lib/portal-contracts.ts": "5e9f5c747eb911a056bb5626d0710c37dbc8aba02a8e054203f736d13511bef7",
|
|
62
|
+
"src/lib/prisma-client.ts": "28cd100129a0178a6c8fdfe49e6997b19983fcc427b9fa7caee3ac26226e5eb3",
|
|
63
|
+
"src/lib/runtime-state.ts": "2bbd9c2d9e963e544a52ac04cc7c5651558cc8b7efd45e179b4eb72d8a640122",
|
|
64
|
+
"src/lib/storage.ts": "ae3b85fc6cccd39d4174a391dcbe6e91fb9460eb407ec9dbfedd63594a441d08",
|
|
65
|
+
"src/lib/token.ts": "518898ca3cbba069f507f736ed80f5afa0c5af07b0b02fdd2d682e466598c803",
|
|
66
|
+
"src/lib/utils.ts": "d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27",
|
|
67
|
+
"src/middleware.ts": "5623ef170d9327e47373943eae33a8b07a6dda970525d0833e0865e4429df094",
|
|
68
|
+
"tailwind.config.ts": "dc0dec22249b290b857190495ce7140327a6f4d94fedd5dffcdb298fa3928071",
|
|
69
|
+
"tests/.gitkeep": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
70
|
+
"tsconfig.json": "1b12f56ab16430b64622ff8512cb05b06cf633060dbec6ebad6f9e792a6dc2a0",
|
|
71
|
+
"vitest.config.ts": "783bfc08b3becc5d8ab0c100700f5c53255d860f9aecb489aedc8eb945f60037"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.2.0
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Database
|
|
2
|
+
# Local development (SQLite, zero config):
|
|
3
|
+
DATABASE_URL="file:./dev.db"
|
|
4
|
+
# Production (PostgreSQL):
|
|
5
|
+
# DATABASE_URL="postgresql://portal:change-me-in-.env@db:5432/portal"
|
|
6
|
+
# POSTGRES_USER="portal"
|
|
7
|
+
# POSTGRES_PASSWORD="change-me-in-.env"
|
|
8
|
+
# POSTGRES_DB="portal"
|
|
9
|
+
|
|
10
|
+
# Auth — generate with: openssl rand -base64 32
|
|
11
|
+
AUTH_SECRET=""
|
|
12
|
+
|
|
13
|
+
# Storage provider: "local" | "s3" | "r2"
|
|
14
|
+
STORAGE_PROVIDER="local"
|
|
15
|
+
|
|
16
|
+
# S3/R2 storage (only needed if STORAGE_PROVIDER is "s3" or "r2")
|
|
17
|
+
# S3_BUCKET=""
|
|
18
|
+
# S3_REGION=""
|
|
19
|
+
# S3_ACCESS_KEY=""
|
|
20
|
+
# S3_SECRET_KEY=""
|
|
21
|
+
# S3_ENDPOINT="" # Required for R2
|
|
22
|
+
|
|
23
|
+
# Public URL (used for share links)
|
|
24
|
+
# NEXT_PUBLIC_APP_URL="https://portal.example.com"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# dependencies
|
|
2
|
+
/node_modules
|
|
3
|
+
/.pnp
|
|
4
|
+
.pnp.js
|
|
5
|
+
|
|
6
|
+
# testing
|
|
7
|
+
/coverage
|
|
8
|
+
|
|
9
|
+
# next.js
|
|
10
|
+
/.next/
|
|
11
|
+
/out/
|
|
12
|
+
|
|
13
|
+
# production
|
|
14
|
+
/build
|
|
15
|
+
|
|
16
|
+
# misc
|
|
17
|
+
.DS_Store
|
|
18
|
+
*.pem
|
|
19
|
+
*.db
|
|
20
|
+
*.db-journal
|
|
21
|
+
|
|
22
|
+
# debug
|
|
23
|
+
npm-debug.log*
|
|
24
|
+
yarn-debug.log*
|
|
25
|
+
yarn-error.log*
|
|
26
|
+
|
|
27
|
+
# local env files
|
|
28
|
+
.env*.local
|
|
29
|
+
.env
|
|
30
|
+
|
|
31
|
+
# vercel
|
|
32
|
+
.vercel
|
|
33
|
+
|
|
34
|
+
# typescript
|
|
35
|
+
*.tsbuildinfo
|
|
36
|
+
next-env.d.ts
|
|
37
|
+
/src/generated/
|
|
38
|
+
|
|
39
|
+
# uploads
|
|
40
|
+
/uploads/
|
|
41
|
+
/private/
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Multi-stage: build Next.js, copy standalone output, add Caddy
|
|
2
|
+
FROM node:20-alpine AS builder
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY package.json package-lock.json* ./
|
|
5
|
+
COPY prisma ./prisma
|
|
6
|
+
RUN npm ci
|
|
7
|
+
COPY . .
|
|
8
|
+
RUN npx prisma generate && npm run build
|
|
9
|
+
|
|
10
|
+
FROM node:20-alpine AS runner
|
|
11
|
+
WORKDIR /app
|
|
12
|
+
|
|
13
|
+
ENV NODE_ENV=production
|
|
14
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
15
|
+
|
|
16
|
+
# Copy Prisma engine, CLI, and schema for migrations
|
|
17
|
+
COPY --from=builder /app/node_modules/.prisma /app/node_modules/.prisma
|
|
18
|
+
COPY --from=builder /app/node_modules/@prisma /app/node_modules/@prisma
|
|
19
|
+
COPY --from=builder /app/node_modules/prisma /app/node_modules/prisma
|
|
20
|
+
COPY --from=builder /app/node_modules/.bin/prisma /app/node_modules/.bin/prisma
|
|
21
|
+
COPY --from=builder /app/prisma /app/prisma
|
|
22
|
+
|
|
23
|
+
# Copy standalone Next.js output
|
|
24
|
+
COPY --from=builder /app/.next/standalone ./
|
|
25
|
+
COPY --from=builder /app/.next/static ./.next/static
|
|
26
|
+
COPY --from=builder /app/public ./public
|
|
27
|
+
|
|
28
|
+
EXPOSE 3000
|
|
29
|
+
|
|
30
|
+
CMD ["sh", "-c", "node node_modules/prisma/build/index.js migrate deploy && node server.js"]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
services:
|
|
2
|
+
portal:
|
|
3
|
+
build:
|
|
4
|
+
context: .
|
|
5
|
+
dockerfile: docker/Dockerfile
|
|
6
|
+
ports:
|
|
7
|
+
- "3000:3000"
|
|
8
|
+
environment:
|
|
9
|
+
DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-portal}:${POSTGRES_PASSWORD:-change-me-in-.env}@db:5432/${POSTGRES_DB:-portal}}
|
|
10
|
+
AUTH_SECRET: ${AUTH_SECRET}
|
|
11
|
+
STORAGE_PROVIDER: ${STORAGE_PROVIDER:-local}
|
|
12
|
+
volumes:
|
|
13
|
+
- uploads:/app/uploads
|
|
14
|
+
depends_on:
|
|
15
|
+
db:
|
|
16
|
+
condition: service_healthy
|
|
17
|
+
restart: unless-stopped
|
|
18
|
+
|
|
19
|
+
caddy:
|
|
20
|
+
image: caddy:2-alpine
|
|
21
|
+
ports:
|
|
22
|
+
- "80:80"
|
|
23
|
+
- "443:443"
|
|
24
|
+
volumes:
|
|
25
|
+
- ./docker/Caddyfile:/etc/caddy/Caddyfile
|
|
26
|
+
- caddy_data:/data
|
|
27
|
+
- caddy_config:/config
|
|
28
|
+
environment:
|
|
29
|
+
DOMAIN: ${DOMAIN:-localhost}
|
|
30
|
+
depends_on:
|
|
31
|
+
- portal
|
|
32
|
+
restart: unless-stopped
|
|
33
|
+
|
|
34
|
+
db:
|
|
35
|
+
image: postgres:16-alpine
|
|
36
|
+
environment:
|
|
37
|
+
POSTGRES_USER: ${POSTGRES_USER:-portal}
|
|
38
|
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me-in-.env}
|
|
39
|
+
POSTGRES_DB: ${POSTGRES_DB:-portal}
|
|
40
|
+
volumes:
|
|
41
|
+
- pgdata:/var/lib/postgresql/data
|
|
42
|
+
healthcheck:
|
|
43
|
+
test: ["CMD-SHELL", "pg_isready -U portal"]
|
|
44
|
+
interval: 5s
|
|
45
|
+
timeout: 5s
|
|
46
|
+
retries: 5
|
|
47
|
+
restart: unless-stopped
|
|
48
|
+
|
|
49
|
+
volumes:
|
|
50
|
+
pgdata:
|
|
51
|
+
uploads:
|
|
52
|
+
caddy_data:
|
|
53
|
+
caddy_config:
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { NextConfig } from "next";
|
|
2
|
+
|
|
3
|
+
const nextConfig: NextConfig = {
|
|
4
|
+
output: "standalone",
|
|
5
|
+
serverExternalPackages: ["@aws-sdk/client-s3"],
|
|
6
|
+
async headers() {
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
source: "/:path*",
|
|
10
|
+
headers: [
|
|
11
|
+
{ key: "X-Content-Type-Options", value: "nosniff" },
|
|
12
|
+
{ key: "X-Frame-Options", value: "DENY" },
|
|
13
|
+
{ key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default nextConfig;
|