create-aphex 0.1.1 → 0.2.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.
Files changed (104) hide show
  1. package/dist/index.js +9 -88
  2. package/package.json +4 -4
  3. package/templates/base/.dockerignore +0 -44
  4. package/templates/base/.env.example +0 -38
  5. package/templates/base/CHANGELOG.md +0 -119
  6. package/templates/base/Dockerfile +0 -69
  7. package/templates/base/README.md +0 -147
  8. package/templates/base/aphex.config.ts +0 -45
  9. package/templates/base/docker-compose.yml +0 -31
  10. package/templates/base/drizzle/0000_tiny_redwing.sql +0 -226
  11. package/templates/base/drizzle/meta/0000_snapshot.json +0 -1379
  12. package/templates/base/drizzle/meta/_journal.json +0 -13
  13. package/templates/base/drizzle.config.ts +0 -17
  14. package/templates/base/package.json +0 -81
  15. package/templates/base/prod.docker-compose.yml +0 -61
  16. package/templates/base/src/app.css +0 -32
  17. package/templates/base/src/app.d.ts +0 -26
  18. package/templates/base/src/app.html +0 -11
  19. package/templates/base/src/hooks.server.ts +0 -52
  20. package/templates/base/src/lib/assets/favicon.svg +0 -5
  21. package/templates/base/src/lib/auth-client.ts +0 -19
  22. package/templates/base/src/lib/index.ts +0 -1
  23. package/templates/base/src/lib/schemaTypes/index.ts +0 -11
  24. package/templates/base/src/lib/schemaTypes/post.ts +0 -47
  25. package/templates/base/src/lib/server/auth/better-auth/instance.ts +0 -165
  26. package/templates/base/src/lib/server/auth/index.ts +0 -25
  27. package/templates/base/src/lib/server/auth/instance.ts +0 -7
  28. package/templates/base/src/lib/server/auth/service.ts +0 -486
  29. package/templates/base/src/lib/server/cache/index.ts +0 -10
  30. package/templates/base/src/lib/server/db/auth-schema.ts +0 -86
  31. package/templates/base/src/lib/server/db/cms-schema.ts +0 -23
  32. package/templates/base/src/lib/server/db/index.ts +0 -55
  33. package/templates/base/src/lib/server/db/schema.ts +0 -3
  34. package/templates/base/src/lib/server/email/components/EmailLayout.svelte +0 -24
  35. package/templates/base/src/lib/server/email/components/EmailVerification.svelte +0 -26
  36. package/templates/base/src/lib/server/email/components/Invitation.svelte +0 -30
  37. package/templates/base/src/lib/server/email/components/PasswordReset.svelte +0 -28
  38. package/templates/base/src/lib/server/email/index.ts +0 -28
  39. package/templates/base/src/lib/server/email/invitation-hook.ts +0 -56
  40. package/templates/base/src/lib/server/email/renderer.ts +0 -13
  41. package/templates/base/src/lib/server/email/templates/email-verification.ts +0 -8
  42. package/templates/base/src/lib/server/email/templates/invitation.ts +0 -8
  43. package/templates/base/src/lib/server/email/templates/password-reset.ts +0 -7
  44. package/templates/base/src/lib/server/services/organization.ts +0 -68
  45. package/templates/base/src/lib/server/storage/index.ts +0 -28
  46. package/templates/base/src/lib/stores/activeTab.svelte.ts +0 -14
  47. package/templates/base/src/lib/utils/imageBuilder.ts +0 -3
  48. package/templates/base/src/lib/utils/slug.ts +0 -33
  49. package/templates/base/src/routes/(protected)/admin/+layout.server.ts +0 -86
  50. package/templates/base/src/routes/(protected)/admin/+layout.svelte +0 -78
  51. package/templates/base/src/routes/(protected)/admin/+page.server.ts +0 -60
  52. package/templates/base/src/routes/(protected)/admin/+page.svelte +0 -34
  53. package/templates/base/src/routes/(protected)/admin/organizations/+page.server.ts +0 -39
  54. package/templates/base/src/routes/(protected)/admin/organizations/+page.svelte +0 -31
  55. package/templates/base/src/routes/(protected)/admin/organizations/_components/CreateOrganization.svelte +0 -141
  56. package/templates/base/src/routes/(protected)/admin/organizations/_components/OrganizationsList.svelte +0 -102
  57. package/templates/base/src/routes/(protected)/admin/settings/+layout.server.ts +0 -42
  58. package/templates/base/src/routes/(protected)/admin/settings/+layout.svelte +0 -116
  59. package/templates/base/src/routes/(protected)/admin/settings/+page.server.ts +0 -16
  60. package/templates/base/src/routes/(protected)/admin/settings/+page.svelte +0 -32
  61. package/templates/base/src/routes/(protected)/admin/settings/_components/AccountSettings.svelte +0 -177
  62. package/templates/base/src/routes/(protected)/admin/settings/_components/ApiKeysSettings.svelte +0 -472
  63. package/templates/base/src/routes/(protected)/admin/settings/_components/OrganizationsSettings.svelte +0 -182
  64. package/templates/base/src/routes/(protected)/admin/settings/account/+page.server.ts +0 -25
  65. package/templates/base/src/routes/(protected)/admin/settings/account/+page.svelte +0 -23
  66. package/templates/base/src/routes/(protected)/admin/settings/api-keys/+page.server.ts +0 -54
  67. package/templates/base/src/routes/(protected)/admin/settings/api-keys/+page.svelte +0 -14
  68. package/templates/base/src/routes/(protected)/admin/settings/members/+page.server.ts +0 -31
  69. package/templates/base/src/routes/(protected)/admin/settings/members/+page.svelte +0 -338
  70. package/templates/base/src/routes/(protected)/admin/settings/roles/+page.server.ts +0 -17
  71. package/templates/base/src/routes/(protected)/admin/settings/roles/+page.svelte +0 -339
  72. package/templates/base/src/routes/+layout.svelte +0 -12
  73. package/templates/base/src/routes/+page.svelte +0 -2
  74. package/templates/base/src/routes/api/[...slug]/+server.ts +0 -35
  75. package/templates/base/src/routes/api/instance-settings/+server.ts +0 -70
  76. package/templates/base/src/routes/api/invitations/+server.ts +0 -54
  77. package/templates/base/src/routes/api/invitations/[id]/accept/+server.ts +0 -54
  78. package/templates/base/src/routes/api/invitations/[id]/reject/+server.ts +0 -49
  79. package/templates/base/src/routes/api/settings/api-keys/+server.ts +0 -57
  80. package/templates/base/src/routes/api/settings/api-keys/[id]/+server.ts +0 -53
  81. package/templates/base/src/routes/god-mode/+layout.server.ts +0 -32
  82. package/templates/base/src/routes/god-mode/+layout.svelte +0 -155
  83. package/templates/base/src/routes/god-mode/+page.server.ts +0 -10
  84. package/templates/base/src/routes/god-mode/+page.svelte +0 -32
  85. package/templates/base/src/routes/god-mode/_components/CreateOrganization.svelte +0 -141
  86. package/templates/base/src/routes/god-mode/_components/OrganizationsList.svelte +0 -169
  87. package/templates/base/src/routes/god-mode/organizations/+page.server.ts +0 -43
  88. package/templates/base/src/routes/god-mode/organizations/+page.svelte +0 -74
  89. package/templates/base/src/routes/invitations/+page.server.ts +0 -48
  90. package/templates/base/src/routes/invitations/+page.svelte +0 -264
  91. package/templates/base/src/routes/invite/[token]/+page.server.ts +0 -59
  92. package/templates/base/src/routes/invite/[token]/+page.svelte +0 -109
  93. package/templates/base/src/routes/login/+page.server.ts +0 -14
  94. package/templates/base/src/routes/login/+page.svelte +0 -332
  95. package/templates/base/src/routes/media/[id]/[filename]/+server.ts +0 -3
  96. package/templates/base/src/routes/reset-password/[token]/+page.server.ts +0 -15
  97. package/templates/base/src/routes/reset-password/[token]/+page.svelte +0 -179
  98. package/templates/base/src/routes/verify-email/+page.svelte +0 -41
  99. package/templates/base/static/images/aphex-darkmode.png +0 -0
  100. package/templates/base/static/images/aphex-lightmode.png +0 -0
  101. package/templates/base/static/robots.txt +0 -3
  102. package/templates/base/svelte.config.js +0 -19
  103. package/templates/base/tsconfig.json +0 -20
  104. package/templates/base/vite.config.ts +0 -138
package/dist/index.js CHANGED
@@ -1,22 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import * as p from '@clack/prompts';
3
- import { existsSync, mkdirSync, cpSync, readFileSync, writeFileSync, readdirSync } from 'fs';
3
+ import { existsSync, readFileSync, writeFileSync, copyFileSync } from 'fs';
4
4
  import { join, resolve } from 'path';
5
- import { fileURLToPath } from 'url';
6
- import { dirname } from 'path';
7
5
  import pc from 'picocolors';
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = dirname(__filename);
10
- const templates = ['base'];
6
+ import { downloadTemplate } from 'giget';
7
+ const TEMPLATE_REPO = process.env.APHEX_TEMPLATE || 'github:IcelandicIcecream/aphex-base';
11
8
  async function main() {
12
9
  console.clear();
13
10
  p.intro(pc.bgCyan(pc.black(' create-aphex ')));
14
11
  const options = {
15
12
  projectName: '',
16
- template: 'base',
17
13
  targetDir: ''
18
14
  };
19
- // Get project name
20
15
  const projectName = await p.text({
21
16
  message: 'What is your project name?',
22
17
  placeholder: 'my-aphex-project',
@@ -34,7 +29,6 @@ async function main() {
34
29
  }
35
30
  options.projectName = projectName;
36
31
  options.targetDir = resolve(process.cwd(), options.projectName);
37
- // Check if directory already exists
38
32
  if (existsSync(options.targetDir)) {
39
33
  const shouldOverwrite = await p.confirm({
40
34
  message: `Directory ${pc.cyan(options.projectName)} already exists. Overwrite?`,
@@ -45,61 +39,28 @@ async function main() {
45
39
  process.exit(0);
46
40
  }
47
41
  }
48
- options.template = 'base';
49
- // Start scaffolding
50
42
  const spinner = p.spinner();
51
- spinner.start('Creating your Aphex project...');
43
+ spinner.start(`Fetching template from ${TEMPLATE_REPO}...`);
52
44
  try {
53
- // Find the templates directory
54
- // When running from npx, we need to look in the right place
55
- const templatesDir = findTemplatesDir();
56
- if (!templatesDir) {
57
- throw new Error('Could not find templates directory');
58
- }
59
- const templatePath = join(templatesDir, options.template);
60
- if (!existsSync(templatePath)) {
61
- throw new Error(`Template "${options.template}" not found`);
62
- }
63
- // Create target directory
64
- mkdirSync(options.targetDir, { recursive: true });
65
- // Copy template files
66
- cpSync(templatePath, options.targetDir, { recursive: true });
67
- // Update package.json with project name and resolve workspace: references
45
+ await downloadTemplate(TEMPLATE_REPO, {
46
+ dir: options.targetDir,
47
+ force: true
48
+ });
68
49
  const packageJsonPath = join(options.targetDir, 'package.json');
69
50
  if (existsSync(packageJsonPath)) {
70
51
  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
71
52
  packageJson.name = options.projectName;
72
- // Replace workspace:* references with actual package versions
73
- for (const depType of ['dependencies', 'devDependencies']) {
74
- const deps = packageJson[depType];
75
- if (!deps)
76
- continue;
77
- for (const [name, version] of Object.entries(deps)) {
78
- if (typeof version === 'string' && version.startsWith('workspace:')) {
79
- // Look up the actual version from the package in the monorepo
80
- const pkgDir = findPackageDir(templatesDir, name);
81
- if (pkgDir) {
82
- const pkgJson = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf-8'));
83
- deps[name] = `^${pkgJson.version}`;
84
- }
85
- }
86
- }
87
- }
88
- // Remove private flag and workspace-specific fields
89
53
  delete packageJson.private;
90
54
  writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, '\t') + '\n');
91
55
  }
92
- // Create .env from .env.example if it doesn't exist
93
56
  const envPath = join(options.targetDir, '.env');
94
57
  const envExamplePath = join(options.targetDir, '.env.example');
95
58
  if (!existsSync(envPath) && existsSync(envExamplePath)) {
96
- cpSync(envExamplePath, envPath);
59
+ copyFileSync(envExamplePath, envPath);
97
60
  }
98
61
  spinner.stop('Project created successfully!');
99
- // Show next steps
100
62
  const nextSteps = [
101
63
  `cd ${options.projectName}`,
102
- 'cp .env.example .env',
103
64
  'pnpm install',
104
65
  'pnpm db:start',
105
66
  'pnpm db:push',
@@ -114,46 +75,6 @@ async function main() {
114
75
  process.exit(1);
115
76
  }
116
77
  }
117
- function findPackageDir(templatesDir, packageName) {
118
- // Templates sit alongside packages/ in the monorepo, or the packages
119
- // are bundled relative to the templates dir in the npm package
120
- const possibleRoots = [
121
- resolve(templatesDir, '..'), // monorepo root (templates/ -> ../)
122
- resolve(templatesDir, '../..') // npm package (dist/templates -> ../../)
123
- ];
124
- for (const root of possibleRoots) {
125
- const packagesDir = join(root, 'packages');
126
- if (!existsSync(packagesDir))
127
- continue;
128
- for (const dir of readdirSync(packagesDir)) {
129
- const pkgJsonPath = join(packagesDir, dir, 'package.json');
130
- if (existsSync(pkgJsonPath)) {
131
- const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
132
- if (pkgJson.name === packageName) {
133
- return join(packagesDir, dir);
134
- }
135
- }
136
- }
137
- }
138
- return null;
139
- }
140
- function findTemplatesDir() {
141
- // Try different possible locations for the templates directory
142
- const possiblePaths = [
143
- // When installed via npm/npx (templates are bundled in package)
144
- resolve(__dirname, '../templates'),
145
- // When running from built dist in package
146
- resolve(__dirname, '../../templates'),
147
- // When running from source in monorepo
148
- resolve(__dirname, '../../../templates')
149
- ];
150
- for (const path of possiblePaths) {
151
- if (existsSync(path)) {
152
- return path;
153
- }
154
- }
155
- return null;
156
- }
157
78
  main().catch((error) => {
158
79
  console.error('Error:', error);
159
80
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-aphex",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Scaffold a new Aphex CMS project — invoked via `pnpm create aphex`",
5
5
  "publishConfig": {
6
6
  "provenance": true
@@ -15,8 +15,7 @@
15
15
  "create-aphex": "./dist/index.js"
16
16
  },
17
17
  "files": [
18
- "dist",
19
- "templates"
18
+ "dist"
20
19
  ],
21
20
  "keywords": [
22
21
  "aphex",
@@ -29,6 +28,7 @@
29
28
  "license": "MIT",
30
29
  "dependencies": {
31
30
  "@clack/prompts": "^0.11.0",
31
+ "giget": "^2.0.0",
32
32
  "picocolors": "^1.1.1"
33
33
  },
34
34
  "devDependencies": {
@@ -36,6 +36,6 @@
36
36
  "typescript": "^5.9.3"
37
37
  },
38
38
  "scripts": {
39
- "build": "node scripts/copy-templates.js && tsc"
39
+ "build": "tsc"
40
40
  }
41
41
  }
@@ -1,44 +0,0 @@
1
- # Build artifacts
2
- build
3
- node_modules
4
- .svelte-kit
5
- dist
6
-
7
- # Environment files
8
- .env
9
- .env.*
10
- !.env.example
11
- !.env.docker
12
-
13
- # OS files
14
- .DS_Store
15
- Thumbs.db
16
-
17
- # Logs
18
- *.log
19
- npm-debug.log*
20
- yarn-debug.log*
21
- yarn-error.log*
22
- pnpm-debug.log*
23
-
24
- # Storage
25
- storage/assets/
26
-
27
- # IDE
28
- .vscode
29
- .idea
30
- *.swp
31
- *.swo
32
-
33
- # Documentation
34
- README.md
35
- CONTRIBUTING.md
36
- LICENSE
37
-
38
- # Git
39
- .git
40
- .gitignore
41
-
42
- # Testing
43
- coverage
44
- .nyc_output
@@ -1,38 +0,0 @@
1
- # ============================
2
- # Database Configuration
3
- # ============================
4
-
5
- ## Option (1): Using a full DATABASE_URL
6
- ## -------------------------------------
7
- DATABASE_URL="postgres://root:mysecretpassword@localhost:5432/local"
8
-
9
- ## Option (2): Using individual connection settings
10
- ## -----------------------------------------------
11
- ## Uncomment and set these if not using DATABASE_URL
12
- # PG_HOST=localhost
13
- # PG_PORT=5432
14
- # PG_USER=root
15
- # PG_PASSWORD=mysecretpassword
16
- # PG_DATABASE=local
17
-
18
- # ============================
19
- # Auth Configuration
20
- # ============================
21
- # BETTER_AUTH_SECRET / BETTER_AUTH_URL also work for backwards compatibility
22
- BETTER_AUTH_SECRET=your-secret-key-here-change-in-production
23
- BETTER_AUTH_URL=http://localhost:5173
24
- AUTH_TRUSTED_ORIGINS=http://localhost:5173
25
-
26
- # ============================
27
- # Resend Email Configuration (optional)
28
- # ============================
29
- RESEND_API_KEY=re_your_api_key_here
30
-
31
- # ============================
32
- # S3_COMPATIBLE CONFIGURATION (optional)
33
- # ============================
34
- R2_ENDPOINT=
35
- R2_ACCESS_KEY_ID=
36
- R2_SECRET_ACCESS_KEY=
37
- R2_BUCKET=
38
- R2_PUBLIC_URL=
@@ -1,119 +0,0 @@
1
- ---
2
- **Heads up:** This project was scaffolded from `@aphexcms/base` `v0.0.3`.
3
- When upgrading, read `CHANGELOG.md` in the template repo for notes on
4
- what changed upstream and which files you may want to port into your
5
- customized project.
6
- ---
7
-
8
- # AphexCMS Template Changelog
9
-
10
- Notes for users upgrading an existing project scaffolded from this template.
11
- Because the template is meant to be customized, changes here are **not**
12
- automatically applied to your project — this file describes what changed
13
- upstream so you can cherry-pick the bits you care about.
14
-
15
- Format: each entry lists the files touched and a one-line reason. Use
16
- `git diff` against the mirror repo (`IcelandicIcecream/aphex-base`) at the
17
- tag matching the version you started from to see the exact changes.
18
-
19
- ## Unreleased
20
-
21
- ## 0.0.3
22
- - **feat(api): move invitation email-wrap into `aphex.config.ts → api`**
23
- - Deleted: `src/routes/api/organizations/invitations/+server.ts` —
24
- the SK shim that wrapped the built-in invite handler to send email.
25
- - Added: `src/lib/server/email/invitation-hook.ts` — same logic, now a
26
- Hono middleware registered via `config.api`. Runs BEFORE built-in
27
- routes mount (Hono is registration-order-strict, so middleware needs
28
- to register first to wrap a downstream handler).
29
- - `aphex.config.ts` now passes `api: (app) => registerInvitationEmailHook(app)`.
30
- - Why: lets us drop the last invitation-related entry from
31
- `routes-exports.ts` and the matching SK route file in cms-core. The
32
- only remaining `routes-exports` entry is `serveAssetCDN` (CDN URLs
33
- live outside `/api` so can't move onto the catch-all).
34
- - Upgrade: copy `src/lib/server/email/invitation-hook.ts` and the new
35
- `api:` block in `aphex.config.ts`; delete your old
36
- `src/routes/api/organizations/invitations/+server.ts`.
37
-
38
- - **feat(api): replace per-endpoint `+server.ts` shims with a single Hono catch-all**
39
- - Added: `src/routes/api/[...slug]/+server.ts` — forwards any unmatched
40
- `/api/**` request to the Aphex Hono app on `event.locals.aphexCMS.apiApp`.
41
- - Deleted (24 files) — all CMS-feature shims that just re-exported handlers
42
- from `@aphexcms/cms-core/server`. They're now served by the catch-all:
43
- - `src/routes/api/{schemas,documents,assets,organizations,roles,user}/+server.ts`
44
- - `src/routes/api/schemas/[type]/+server.ts`
45
- - `src/routes/api/documents/{query,[id]}/+server.ts`
46
- - `src/routes/api/documents/[id]/{publish,versions}/+server.ts`
47
- - `src/routes/api/documents/[id]/versions/[version]/+server.ts`
48
- - `src/routes/api/documents/[id]/versions/[version]/restore/+server.ts`
49
- - `src/routes/api/assets/{bulk,[id]}/+server.ts`
50
- - `src/routes/api/assets/[id]/references/+server.ts`
51
- - `src/routes/api/assets/references/counts/+server.ts`
52
- - `src/routes/api/organizations/{switch,members,[id]}/+server.ts`
53
- - `src/routes/api/roles/[name]/+server.ts`
54
- - `src/routes/api/user/{cms-preference,reset-password,request-password-reset}/+server.ts`
55
- - Kept (studio-locals — your own endpoints): `instance-settings`,
56
- `invitations`, `invitations/[id]/{accept,reject}`,
57
- `organizations/invitations`, `settings/api-keys`, `settings/api-keys/[id]`.
58
- - Why: SvelteKit prefers specific routes over the catch-all, so any
59
- `+server.ts` you keep wins. Custom endpoints can still go in
60
- `src/routes/**/+server.ts` as before, OR be registered onto the Hono
61
- app via `aphex.config.ts → api: (app) => { app.post(...) }`.
62
- - Upgrade: copy `src/routes/api/[...slug]/+server.ts` from the template,
63
- then delete any of the 24 shims you haven't customized. If you
64
- customized one, leave it — it'll continue to win over the catch-all.
65
-
66
- ## 0.0.2
67
-
68
- - **chore(deps): bump `@aphexcms/cms-core` to `^2.1.2` and `@aphexcms/ui` to `^0.3.4`**
69
- - Fixes ESM resolution of the `schema-context.svelte` rune module
70
- (`ERR_MODULE_NOT_FOUND`) and adds the `svelte` export condition on
71
- subpath exports (`/client`, `/server`, `/schema`, `/routes/*`, etc.) so
72
- SvelteKit's Vite plugin claims them instead of Node's default loader
73
- trying to import raw `.svelte` files (`ERR_UNKNOWN_FILE_EXTENSION`).
74
- - No source changes required in the template — reinstall to pick it up.
75
-
76
- - **chore(styles): drop `@import '@aphexcms/ui/themes/aphex'` from `src/app.css`**
77
- - The `@aphexcms/ui/themes/aphex` theme file was removed from
78
- `@aphexcms/ui@0.3.4`. If you kept that import in your own `app.css`,
79
- delete the line when you upgrade or the build will fail to resolve it.
80
-
81
- - **fix(admin): delete-asset modal + document-editor header + boolean autosave**
82
- - All three fixes live in `@aphexcms/cms-core`; upgrading the dep is enough.
83
- - Long asset filenames no longer stretch the delete confirm dialog.
84
- - Document editor top-row actions are vertically centered.
85
- - Autosave compares against an initial-defaults snapshot — unchecking a
86
- boolean now saves, and fields with `initialValue: true` no longer
87
- auto-create an empty doc on mount.
88
-
89
- - **chore(drizzle): regenerate initial migration**
90
- - `drizzle/0000_tiny_redwing.sql`, `drizzle/meta/0000_snapshot.json`, `drizzle/meta/_journal.json`
91
- - Template migration was stale vs. the current schema (missing
92
- `cms_document_versions`, `cms_instance_settings`, `cms_roles`, the
93
- `version_event` enum, and the `unpublished` document status).
94
- - If you've already run `db:push` against your project DB you're fine;
95
- users starting fresh from this template will now get the full schema.
96
-
97
- - **chore(admin): comment out `<PermissionsDebug />`**
98
- - `src/routes/(protected)/admin/+layout.svelte`
99
- - Debug overlay disabled by default in the shipped template.
100
-
101
- <!--
102
- Example entry:
103
-
104
- - **fix(members): reject self-invitation and duplicate members**
105
- - `src/routes/(protected)/admin/settings/members/+page.svelte`
106
- - Handled server-side in cms-core; UI unchanged. Safe to skip if you
107
- haven't customized the invite flow.
108
-
109
- - **feat(versions): add document versions API routes**
110
- - `src/routes/api/documents/[id]/versions/+server.ts`
111
- - `src/routes/api/documents/[id]/versions/[version]/+server.ts`
112
- - `src/routes/api/documents/[id]/versions/[version]/restore/+server.ts`
113
- - Clean re-exports from `@aphexcms/cms-core/server`. Port these over to
114
- get version history in your admin UI.
115
- -->
116
-
117
- ## 0.0.1
118
-
119
- - Initial template.
@@ -1,69 +0,0 @@
1
- # Build stage
2
- FROM node:20-alpine AS builder
3
-
4
- # Install pnpm
5
- RUN npm install -g pnpm
6
-
7
- WORKDIR /app
8
-
9
- # Copy workspace files
10
- COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
11
- COPY turbo.json ./
12
- COPY tsconfig.json ./
13
-
14
- # Copy all packages and apps
15
- COPY packages ./packages
16
- COPY apps/studio ./apps/studio
17
-
18
- # Install dependencies
19
- RUN pnpm install --frozen-lockfile
20
-
21
- # Build arguments for environment variables needed at build time
22
- ARG ACCESS_API_KEY
23
- ARG GITHUB_TOKEN
24
- ARG RESEND_API_KEY
25
- ARG AUTH_SECRET
26
- ARG AUTH_URL
27
- ARG DATABASE_URL
28
-
29
- # Set as environment variables for the build
30
- ENV ACCESS_API_KEY=$ACCESS_API_KEY
31
- ENV GITHUB_TOKEN=$GITHUB_TOKEN
32
- ENV RESEND_API_KEY=$RESEND_API_KEY
33
- ENV AUTH_SECRET=$AUTH_SECRET
34
- ENV AUTH_URL=$AUTH_URL
35
- ENV DATABASE_URL=$DATABASE_URL
36
-
37
- # Build the application
38
- WORKDIR /app/apps/studio
39
- RUN pnpm build
40
-
41
- # Production stage
42
- FROM node:20-alpine AS runner
43
-
44
- # Copy workspace root files first
45
- COPY --from=builder /app/package.json /app/package.json
46
- COPY --from=builder /app/pnpm-workspace.yaml /app/pnpm-workspace.yaml
47
- COPY --from=builder /app/node_modules /app/node_modules
48
- COPY --from=builder /app/packages /app/packages
49
-
50
- # Set working directory for the app
51
- WORKDIR /app/apps/studio
52
-
53
- # Copy studio app files
54
- COPY --from=builder /app/apps/studio/build ./build
55
- COPY --from=builder /app/apps/studio/package.json ./package.json
56
- COPY --from=builder /app/apps/studio/node_modules ./node_modules
57
- COPY --from=builder /app/apps/studio/drizzle ./drizzle
58
- COPY --from=builder /app/apps/studio/drizzle.config.ts ./drizzle.config.ts
59
-
60
- # Expose port
61
- EXPOSE 3000
62
-
63
- # Set environment to production
64
- ENV NODE_ENV=production
65
- ENV PORT=3000
66
- ENV NODE_PATH=/app/node_modules
67
-
68
- # Start the application
69
- CMD ["node", "build"]
@@ -1,147 +0,0 @@
1
- # Aphex CMS
2
-
3
- A clean starting point for building with Aphex CMS. No example schemas — just the wiring.
4
-
5
- > This directory is mirrored to [**IcelandicIcecream/aphex-base**](https://github.com/IcelandicIcecream/aphex-base) on every change, so you can clone it directly as a standalone project:
6
- >
7
- > ```bash
8
- > git clone https://github.com/IcelandicIcecream/aphex-base my-app
9
- > cd my-app && pnpm install
10
- > ```
11
- >
12
- > Or scaffold via the CLI: `pnpm aphex create`.
13
-
14
- ## Getting Started
15
-
16
- ### 1. Install Dependencies
17
-
18
- ```bash
19
- pnpm install
20
- ```
21
-
22
- ### 2. Set Up Environment Variables
23
-
24
- Copy the example file and update as needed:
25
-
26
- ```bash
27
- cp .env.example .env
28
- ```
29
-
30
- ### 3. Start PostgreSQL Database
31
-
32
- ```bash
33
- pnpm db:start
34
- ```
35
-
36
- ### 4. Run Database Migrations
37
-
38
- ```bash
39
- pnpm db:migrate
40
- ```
41
-
42
- ### 5. Start Development Server
43
-
44
- ```bash
45
- pnpm dev
46
- ```
47
-
48
- Your application will be available at `http://localhost:5173`
49
-
50
- ### 6. First Login
51
-
52
- 1. Go to `http://localhost:5173/login`
53
- 2. Sign up with your email and password — the first user automatically becomes the super admin with a default organization
54
- 3. Access God Mode at `/god-mode` for instance-level administration
55
-
56
- ## Defining Content Schemas
57
-
58
- Add your content schemas in `src/lib/schemaTypes/`. Two types are available:
59
-
60
- - **`document`** — Top-level entities (e.g. Page, Post, Product)
61
- - **`object`** — Reusable nested structures (e.g. SEO, Hero)
62
-
63
- Example:
64
-
65
- ```typescript
66
- // src/lib/schemaTypes/post.ts
67
- import type { SchemaType } from '@aphexcms/cms-core';
68
-
69
- const post: SchemaType = {
70
- type: 'document',
71
- name: 'post',
72
- title: 'Post',
73
- fields: [
74
- {
75
- name: 'title',
76
- type: 'string',
77
- title: 'Title',
78
- validation: (Rule) => Rule.required()
79
- },
80
- {
81
- name: 'slug',
82
- type: 'slug',
83
- title: 'Slug',
84
- source: 'title'
85
- },
86
- {
87
- name: 'body',
88
- type: 'text',
89
- title: 'Body'
90
- }
91
- ]
92
- };
93
-
94
- export default post;
95
- ```
96
-
97
- Then register it in `src/lib/schemaTypes/index.ts`:
98
-
99
- ```typescript
100
- import post from './post.js';
101
-
102
- export const schemaTypes = [post];
103
- ```
104
-
105
- Available field types: `string`, `text`, `number`, `boolean`, `slug`, `image`, `date`, `datetime`, `url`, `array`, `object`, `reference`
106
-
107
- ## Available Scripts
108
-
109
- - `pnpm dev` — Start the development server
110
- - `pnpm build` — Build for production
111
- - `pnpm preview` — Preview production build
112
- - `pnpm db:start` — Start PostgreSQL via Docker
113
- - `pnpm db:migrate` — Run database migrations
114
- - `pnpm db:push` — Push schema changes (dev only)
115
- - `pnpm db:generate` — Generate migration files
116
- - `pnpm db:studio` — Open Drizzle Studio
117
-
118
- ## Project Structure
119
-
120
- ```
121
- .
122
- ├── src/
123
- │ ├── lib/
124
- │ │ ├── server/
125
- │ │ │ ├── auth/ # Authentication (Better Auth)
126
- │ │ │ ├── db/ # Database connection and schema
127
- │ │ │ ├── email/ # Email templates and adapter
128
- │ │ │ ├── services/ # Business logic
129
- │ │ │ └── storage/ # File storage adapter
130
- │ │ ├── schemaTypes/ # Your content type definitions
131
- │ │ └── utils/ # Utility functions
132
- │ └── routes/
133
- │ ├── (protected)/admin/ # Admin panel
134
- │ ├── api/ # API endpoints
135
- │ ├── god-mode/ # Super admin panel
136
- │ └── login/ # Authentication
137
- ├── aphex.config.ts # CMS configuration
138
- ├── drizzle/ # Database migrations
139
- └── docker-compose.yml # PostgreSQL setup
140
- ```
141
-
142
- ## Learn More
143
-
144
- - [Aphex CMS](https://github.com/IcelandicIcecream/aphex)
145
- - [SvelteKit](https://kit.svelte.dev)
146
- - [Drizzle ORM](https://orm.drizzle.team)
147
- - [Better Auth](https://better-auth.com)
@@ -1,45 +0,0 @@
1
- // Aphex CMS Configuration
2
- // This file defines the CMS configuration for your application
3
- import { createCMSConfig } from '@aphexcms/cms-core/server';
4
- import { schemaTypes } from './src/lib/schemaTypes/index.js';
5
- import { authProvider } from './src/lib/server/auth';
6
- import { db } from './src/lib/server/db';
7
- import { email } from './src/lib/server/email';
8
- import { registerInvitationEmailHook } from './src/lib/server/email/invitation-hook';
9
- import { storageAdapter } from './src/lib/server/storage';
10
- import { cacheAdapter } from './src/lib/server/cache';
11
-
12
- export default createCMSConfig({
13
- schemaTypes,
14
-
15
- // Provide the shared database and storage adapter instances directly.
16
- // These are created once in their respective /lib/server/.. files.
17
- database: db,
18
- storage: storageAdapter,
19
- email,
20
- cache: cacheAdapter,
21
-
22
- auth: {
23
- provider: authProvider,
24
- loginUrl: '/login' // Redirect here when unauthenticated
25
- },
26
-
27
- // GraphQL is built-in and enabled by default.
28
- // Set to false to disable, or pass config: { defaultPerspective: 'draft', path: '/api/graphql' }
29
- graphql: {
30
- defaultPerspective: 'draft',
31
- path: '/api/aphex-graphql'
32
- },
33
-
34
- customization: {
35
- branding: {
36
- title: 'Aphex'
37
- }
38
- },
39
-
40
- // Wrap built-in handlers with side effects (e.g. send the invitation
41
- // email after the invite is created). Runs BEFORE built-in routes mount.
42
- api: (app) => {
43
- registerInvitationEmailHook(app);
44
- }
45
- });
@@ -1,31 +0,0 @@
1
- services:
2
- db:
3
- image: postgres:18
4
- restart: always
5
- env_file:
6
- - .env
7
- ports:
8
- - ${PG_PORT:-5432}:5432
9
- environment:
10
- POSTGRES_USER: ${PG_USER:-root}
11
- POSTGRES_PASSWORD: ${PG_PASSWORD:-mysecretpassword}
12
- POSTGRES_DB: ${PG_DATABASE:-local}
13
- volumes:
14
- - pgdata:/var/lib/postgresql
15
-
16
- mailpit:
17
- image: axllent/mailpit
18
- ports:
19
- - 8025:8025
20
- - 1025:1025
21
- environment:
22
- MP_MAX_MESSAGES: 5000
23
- MP_DATABASE: /data/mailpit.db
24
- MP_SMTP_AUTH_ACCEPT_ANY: 1
25
- MP_SMTP_AUTH_ALLOW_INSECURE: 1
26
- volumes:
27
- - mailpit_data:/data
28
-
29
- volumes:
30
- pgdata:
31
- mailpit_data: