create-ampless 0.2.0-alpha.0 → 0.2.0-alpha.10

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 (29) hide show
  1. package/README.md +36 -0
  2. package/dist/index.js +2098 -48
  3. package/dist/templates/_shared/amplify/auth/resource.ts +7 -2
  4. package/dist/templates/_shared/amplify/backend.custom.ts +41 -0
  5. package/dist/templates/_shared/amplify/backend.ts +10 -2
  6. package/dist/templates/_shared/amplify/data/resource.custom.ts +33 -0
  7. package/dist/templates/_shared/amplify/data/resource.ts +23 -15
  8. package/dist/templates/_shared/amplify/functions/user-admin/handler.ts +4 -0
  9. package/dist/templates/_shared/amplify/functions/user-admin/resource.ts +6 -0
  10. package/dist/templates/_shared/amplify/storage/resource.ts +7 -2
  11. package/dist/templates/_shared/amplify.yml +18 -0
  12. package/dist/templates/_shared/app/(admin)/admin/users/page.tsx +5 -0
  13. package/dist/templates/_shared/app/site/[siteId]/[...path]/route.ts +17 -0
  14. package/dist/templates/_shared/components/i18n-provider.tsx +8 -0
  15. package/dist/templates/_shared/lib/admin-site.ts +6 -2
  16. package/dist/templates/_shared/lib/admin.ts +10 -4
  17. package/dist/templates/_shared/lib/amplify.ts +17 -6
  18. package/dist/templates/_shared/lib/auth-server.ts +7 -3
  19. package/dist/templates/_shared/lib/i18n.ts +5 -1
  20. package/dist/templates/_shared/lib/posts-public.ts +11 -3
  21. package/dist/templates/_shared/lib/seo.ts +5 -2
  22. package/dist/templates/_shared/lib/site-settings.ts +4 -1
  23. package/dist/templates/_shared/lib/storage.ts +5 -2
  24. package/dist/templates/_shared/lib/theme-active.ts +3 -1
  25. package/dist/templates/_shared/lib/theme-config.ts +3 -1
  26. package/dist/templates/_shared/package.json +22 -19
  27. package/dist/templates/_shared/proxy.ts +33 -0
  28. package/package.json +3 -2
  29. package/dist/templates/_shared/middleware.ts +0 -13
@@ -1,8 +1,13 @@
1
- import { defineAmplessAuth } from '@ampless/backend'
1
+ import { defineAuth } from '@aws-amplify/backend'
2
+ import { amplessAuthConfig } from '@ampless/backend'
2
3
  import { postConfirmation } from './post-confirmation/resource.js'
3
4
 
4
5
  // Provisions a Cognito User Pool + Identity Pool with the three role
5
6
  // groups (ampless-admin, ampless-editor, ampless-reader) and wires in
6
7
  // the post-confirmation Lambda that promotes the first confirmed user
7
8
  // to ampless-admin.
8
- export const auth = defineAmplessAuth({ postConfirmation })
9
+ //
10
+ // `defineAuth` must be called from this file directly — Amplify Gen 2's
11
+ // import-path verifier requires it to live at amplify/auth/resource.ts.
12
+ // `amplessAuthConfig` just returns the props object.
13
+ export const auth = defineAuth(amplessAuthConfig({ postConfirmation }))
@@ -0,0 +1,41 @@
1
+ import type { AmplessBackend } from '@ampless/backend'
2
+
3
+ // Custom backend extensions for this project.
4
+ //
5
+ // `amplify/backend.ts` calls `customizeBackend(backend)` right after
6
+ // ampless's baseline wiring. Mutate the passed `backend` instance to
7
+ // add Lambda permissions, attach event sources, register custom CDK
8
+ // constructs, etc.
9
+ //
10
+ // This file is NEVER overwritten by `create-ampless upgrade` —
11
+ // `amplify/backend.ts` is, so keep your customizations here.
12
+ //
13
+ // (Function-export rather than side-effect import on purpose: a
14
+ // top-level `import { backend } from './backend.js'` would create an
15
+ // ESM circular dependency, leaving `backend` in its TDZ at evaluation
16
+ // time. The factory pattern sidesteps that.)
17
+ //
18
+ // Example: granting an existing ampless Lambda extra IAM permissions:
19
+ //
20
+ // import { Effect, PolicyStatement } from 'aws-cdk-lib/aws-iam'
21
+ //
22
+ // export function customizeBackend(backend: AmplessBackend): void {
23
+ // backend.processorTrusted.resources.lambda.addToRolePolicy(
24
+ // new PolicyStatement({
25
+ // effect: Effect.ALLOW,
26
+ // actions: ['ses:SendEmail'],
27
+ // resources: ['*'],
28
+ // })
29
+ // )
30
+ // }
31
+ //
32
+ // Example: adding your own Lambda function — define it in
33
+ // `amplify/functions/<name>/resource.ts`, import it here, and attach
34
+ // it inside `customizeBackend` via `backend.createStack(...)` or by
35
+ // granting it permissions on existing resources.
36
+ //
37
+ // If you don't need any extensions, leave the body empty.
38
+
39
+ export function customizeBackend(_backend: AmplessBackend): void {
40
+ // No-op by default.
41
+ }
@@ -8,13 +8,16 @@ import { eventDispatcher } from './events/dispatcher/resource.js'
8
8
  import { processorTrusted } from './events/processor-trusted/resource.js'
9
9
  import { processorUntrusted } from './events/processor-untrusted/resource.js'
10
10
  import { apiKeyRenewer } from './functions/api-key-renewer/resource.js'
11
+ import { userAdmin } from './functions/user-admin/resource.js'
12
+ import { customizeBackend } from './backend.custom.js'
11
13
 
12
14
  // `defineAmplessBackend` provisions auth, data, storage, the event
13
15
  // system (DynamoDB Streams → SQS-trusted / SQS-untrusted → trust_level
14
16
  // Lambdas), the AppSync API key renewer, and every IAM / CORS /
15
17
  // password policy override. Add custom CDK constructs / IAM policies
16
- // below by mutating the returned `backend` — `defineAmplessBackend`
17
- // returns the same object Amplify Gen 2's `defineBackend` does.
18
+ // in `amplify/backend.custom.ts` by mutating the `backend` instance
19
+ // `defineAmplessBackend` returns the same object Amplify Gen 2's
20
+ // `defineBackend` does.
18
21
  const backend = defineAmplessBackend({
19
22
  auth,
20
23
  data,
@@ -24,6 +27,11 @@ const backend = defineAmplessBackend({
24
27
  processorTrusted,
25
28
  processorUntrusted,
26
29
  apiKeyRenewer,
30
+ userAdmin,
27
31
  })
28
32
 
33
+ // Run user-defined customizations after baseline wiring. `backend.custom.ts`
34
+ // is never overwritten by `create-ampless upgrade`.
35
+ customizeBackend(backend)
36
+
29
37
  export default backend
@@ -0,0 +1,33 @@
1
+ // Custom data schema models for this project.
2
+ //
3
+ // `amplify/data/resource.ts` calls `customSchemaModels(a)` and spreads
4
+ // the result alongside ampless's built-in models in the same
5
+ // `a.schema({...})` call, which is the only way Amplify Gen 2's
6
+ // `ClientSchema<typeof schema>` inference picks up extra models.
7
+ //
8
+ // This file is NEVER overwritten by `create-ampless upgrade` —
9
+ // `amplify/data/resource.ts` is, so keep your custom models here.
10
+ //
11
+ // Example:
12
+ //
13
+ // export function customSchemaModels(a: any) {
14
+ // return {
15
+ // Bookmark: a
16
+ // .model({
17
+ // siteId: a.string().required(),
18
+ // bookmarkId: a.id().required(),
19
+ // url: a.string().required(),
20
+ // title: a.string(),
21
+ // })
22
+ // .identifier(['siteId', 'bookmarkId'])
23
+ // .authorization((allow: any) => [allow.groups(['ampless-admin', 'ampless-editor'])]),
24
+ // }
25
+ // }
26
+ //
27
+ // `a` is the Amplify Gen 2 schema builder; see Amplify Data docs for
28
+ // the full DSL. Return an empty object if no customizations are needed.
29
+
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ export function customSchemaModels(_a: any): Record<string, unknown> {
32
+ return {}
33
+ }
@@ -1,26 +1,34 @@
1
+ import { fileURLToPath } from 'node:url'
2
+ import { dirname, resolve } from 'node:path'
1
3
  import { a, defineData, type ClientSchema } from '@aws-amplify/backend'
2
4
  import { amplessSchemaModels, defaultAuthorizationModes } from '@ampless/backend'
5
+ import { userAdmin } from '../functions/user-admin/resource.js'
6
+ import { customSchemaModels } from './resource.custom.js'
7
+
8
+ // AppSync's `a.handler.custom({ entry })` paths are resolved by CDK
9
+ // relative to the file that called `a.handler.custom`. When the call
10
+ // originates inside `@ampless/backend` (via amplessSchemaModels), the
11
+ // CDK synth tries to resolve `./list-published-posts.js` relative to
12
+ // `node_modules/@ampless/backend/dist/index.js` and fails with
13
+ // `UnresolvedEntryPathError`. Anchor the resolver paths at THIS file's
14
+ // directory so the result is unambiguous.
15
+ const __dirname = dirname(fileURLToPath(import.meta.url))
3
16
 
4
17
  // Ampless's built-in models (Post / Page / Media / Taxonomy / PostTag /
5
18
  // KvStore) plus the three public-read custom queries
6
19
  // (listPublishedPosts / getPublishedPost / listPostsByTag).
7
20
  //
8
- // Add project-specific models alongside the spread:
9
- //
10
- // const schema = a.schema({
11
- // ...amplessSchemaModels(a),
12
- // MyCustomModel: a
13
- // .model({ siteId: a.string().required(), foo: a.string() })
14
- // .identifier(['siteId', 'foo'])
15
- // .authorization((allow) => [allow.groups(['ampless-admin'])]),
16
- // })
17
- //
18
- // The three AppSync JS resolvers (`*.js` in this directory) stay
19
- // user-owned — AppSync resolves `entry: './...'` paths at synth time
20
- // relative to this file. If you relocate them, pass new paths via
21
- // `amplessSchemaModels(a, { resolverPaths: { ... } })`.
21
+ // Add project-specific models in `amplify/data/resource.custom.ts`
22
+ // that file is never overwritten by `create-ampless upgrade`.
23
+ const resolverPaths = {
24
+ listPublishedPosts: resolve(__dirname, 'list-published-posts.js'),
25
+ getPublishedPost: resolve(__dirname, 'get-published-post.js'),
26
+ listPostsByTag: resolve(__dirname, 'list-posts-by-tag.js'),
27
+ }
28
+
22
29
  const schema = a.schema({
23
- ...amplessSchemaModels(a),
30
+ ...amplessSchemaModels(a, { resolverPaths, userAdminFunction: userAdmin }),
31
+ ...customSchemaModels(a),
24
32
  })
25
33
 
26
34
  export type Schema = ClientSchema<typeof schema>
@@ -0,0 +1,4 @@
1
+ // Re-exported from @ampless/backend so the package can ship Lambda
2
+ // handler updates via `npm update`. Amplify's esbuild follows this
3
+ // import and bundles the real handler into the Lambda artifact.
4
+ export { handler } from '@ampless/backend/auth/user-admin'
@@ -0,0 +1,6 @@
1
+ import { defineFunction } from '@aws-amplify/backend'
2
+
3
+ export const userAdmin = defineFunction({
4
+ name: 'user-admin',
5
+ entry: './handler.ts',
6
+ })
@@ -1,7 +1,12 @@
1
- import { defineAmplessStorage } from '@ampless/backend'
1
+ import { defineStorage } from '@aws-amplify/backend'
2
+ import { amplessStorageConfig } from '@ampless/backend'
2
3
 
3
4
  // Provisions the ampless media + plugins bucket with guest read on
4
5
  // `public/*` and admin/editor write on the matched prefixes. CORS and
5
6
  // the bucket-level public-access policy are applied by
6
7
  // defineAmplessBackend.
7
- export const storage = defineAmplessStorage()
8
+ //
9
+ // `defineStorage` must be called from this file directly — Amplify Gen 2's
10
+ // import-path verifier requires it to live at amplify/storage/resource.ts.
11
+ // `amplessStorageConfig` just returns the props object.
12
+ export const storage = defineStorage(amplessStorageConfig())
@@ -0,0 +1,18 @@
1
+ version: 1
2
+ frontend:
3
+ phases:
4
+ preBuild:
5
+ commands:
6
+ - npm install
7
+ build:
8
+ commands:
9
+ - npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID
10
+ - npm run build
11
+ artifacts:
12
+ baseDirectory: .next
13
+ files:
14
+ - '**/*'
15
+ cache:
16
+ paths:
17
+ - node_modules/**/*
18
+ - .next/cache/**/*
@@ -0,0 +1,5 @@
1
+ import { admin } from '@/lib/admin'
2
+ import { createUsersListPage } from '@ampless/admin/pages'
3
+
4
+ export const dynamic = 'force-dynamic'
5
+ export default createUsersListPage(admin)
@@ -0,0 +1,17 @@
1
+ import { ampless } from '@/lib/ampless'
2
+ import { createStaticRouteHandler } from '@ampless/runtime/routes'
3
+
4
+ // Catch-all handler for `format: 'static'` post bundles. Lives here
5
+ // instead of under a dedicated `/static/` prefix so the published URL
6
+ // stays a clean `/<slug>/…`, matching how a developer would host a
7
+ // hand-written landing page locally. The runtime handler enforces
8
+ // `format === 'static'` and 404s for any other post format reaching
9
+ // this route.
10
+ //
11
+ // Routing precedence: Next.js prefers the more specific
12
+ // `[siteId]/[slug]/page.tsx` for single-segment URLs, so the regular
13
+ // theme post dispatcher keeps handling normal posts. This catch-all
14
+ // only fires for multi-segment requests (e.g. `/promo/index.html`,
15
+ // `/promo/assets/style.css`).
16
+ export const dynamic = 'force-dynamic'
17
+ export const GET = createStaticRouteHandler(ampless)
@@ -1,7 +1,15 @@
1
+ 'use client'
2
+
1
3
  // Back-compat shim. I18n provider + hooks moved to `@ampless/admin`
2
4
  // (L2 extraction). The component tree mounts the provider inside the
3
5
  // admin layout factory; the root layout in `app/layout.tsx` still
4
6
  // wraps the public site in this same provider to keep client-side
5
7
  // `useT()` calls working from theme-side components too.
8
+ //
9
+ // The `'use client'` directive is needed because the bundled
10
+ // @ampless/admin/components ESM strips per-file 'use client' (tsup
11
+ // default behaviour). This shim re-establishes a client boundary so
12
+ // Next.js doesn't try to evaluate the React hooks inside an RSC
13
+ // server context.
6
14
 
7
15
  export { I18nProvider, useT, useLocale } from '@ampless/admin/components'
@@ -4,5 +4,9 @@
4
4
 
5
5
  import { admin } from './admin'
6
6
 
7
- export const currentAdminSiteId = admin.currentAdminSiteId.bind(admin)
8
- export const adminSiteOptions = admin.adminSiteOptions.bind(admin)
7
+ // Arrow wrappers: defer `admin` resolution to call time (avoid TDZ in
8
+ // case of circular import chains touching admin shims).
9
+ export const currentAdminSiteId: typeof admin.currentAdminSiteId =
10
+ (...args) => admin.currentAdminSiteId(...args)
11
+ export const adminSiteOptions: typeof admin.adminSiteOptions =
12
+ (...args) => admin.adminSiteOptions(...args)
@@ -4,18 +4,24 @@
4
4
  //
5
5
  // L2 architectural change (admin extraction): admin UI now lives in
6
6
  // `@ampless/admin`. This module wires the project's
7
- // `amplify_outputs.json`, `cms.config`, and `ampless` runtime into a
8
- // single `Admin` instance.
7
+ // `amplify_outputs.json` and `cms.config` into a single `Admin`
8
+ // instance.
9
+ //
10
+ // NOTE: We intentionally do NOT pass an `ampless` instance to
11
+ // createAdmin. That would import `lib/ampless.ts`, which imports
12
+ // `themes-registry`, which (via theme pages → `lib/i18n.ts`) imports
13
+ // back to this file — a circular chain that crashes with a TDZ
14
+ // ReferenceError on `ampless` at module init. `createAdmin` builds
15
+ // its own internal Ampless when omitted, which is functionally
16
+ // equivalent for admin's needs.
9
17
 
10
18
  import outputs from '../amplify_outputs.json'
11
19
  import cmsConfig from '@/cms.config'
12
20
  import { createAdmin } from '@ampless/admin'
13
- import { ampless } from './ampless'
14
21
 
15
22
  export const admin = createAdmin({
16
23
  outputs,
17
24
  cmsConfig,
18
- ampless,
19
25
  locale: (cmsConfig as { locale?: string }).locale ?? 'en',
20
26
  })
21
27
 
@@ -1,9 +1,20 @@
1
- // Back-compat shim. The Amplify SDK is now configured by the admin's
2
- // `<AdminProviders>` bootstrap (mounted by the layout factory in
3
- // `@ampless/admin/pages`), so most call sites no longer need to call
4
- // `configureAmplify()` themselves. Kept as a no-op so any lingering
5
- // `import '@/lib/amplify'` side-effect imports stay safe.
1
+ // Client-side Amplify SDK setup. Imported as a side-effect from
2
+ // `app/providers.tsx` so it runs on every page load (public + admin +
3
+ // login). `<AdminProviders>` (mounted by the admin layout factory)
4
+ // also performs this configuration, but it only runs for routes under
5
+ // the (admin) group; `/login` is a top-level route outside that group
6
+ // and would otherwise hit "Auth UserPool not configured" because no
7
+ // AdminProviders has bootstrapped the SDK yet.
8
+ //
9
+ // `Amplify.configure` is idempotent — calling it once at the root and
10
+ // again inside AdminProviders is harmless.
11
+
12
+ import { Amplify } from 'aws-amplify'
13
+ import outputs from '../amplify_outputs.json'
14
+
15
+ Amplify.configure(outputs, { ssr: true })
6
16
 
7
17
  export function configureAmplify() {
8
- // intentionally empty admin bootstrap handles this
18
+ // module-level side effect above already ran; keep this as a no-op
19
+ // for callers that still import it as a function for back-compat.
9
20
  }
@@ -6,6 +6,10 @@ import { admin } from './admin'
6
6
 
7
7
  export type { ServerSession } from '@ampless/admin'
8
8
 
9
- export const getServerSession = admin.getServerSession.bind(admin)
10
- export const isAdmin = admin.isAdmin.bind(admin)
11
- export const isEditor = admin.isEditor.bind(admin)
9
+ // Arrow wrappers: defer `admin` resolution to call time (avoid TDZ).
10
+ export const getServerSession: typeof admin.getServerSession =
11
+ (...args) => admin.getServerSession(...args)
12
+ export const isAdmin: typeof admin.isAdmin =
13
+ (...args) => admin.isAdmin(...args)
14
+ export const isEditor: typeof admin.isEditor =
15
+ (...args) => admin.isEditor(...args)
@@ -20,7 +20,11 @@ export function getDictionary(locale: Locale = admin.locale): Dictionary {
20
20
  return adminGetDictionary(locale)
21
21
  }
22
22
 
23
- export const t = admin.t
23
+ // Arrow wrapper: defer `admin` resolution to call time. If a future
24
+ // circular import chain triggers i18n.ts before admin.ts has finished
25
+ // initialising, eager `admin.t` would TDZ; calling the method through
26
+ // a wrapper avoids that.
27
+ export const t: typeof admin.t = (key, vars) => admin.t(key, vars)
24
28
 
25
29
  export function translate(
26
30
  _dict: Dictionary,
@@ -8,9 +8,17 @@
8
8
 
9
9
  import { ampless } from './ampless'
10
10
 
11
- export const listPublishedPosts = ampless.listPublishedPosts.bind(ampless)
12
- export const getPublishedPost = ampless.getPublishedPost.bind(ampless)
13
- export const listPostsByTag = ampless.listPostsByTag.bind(ampless)
11
+ // Arrow function wrappers (not `.bind(ampless)`) so the `ampless`
12
+ // binding is read at call time, not at module evaluation. Module
13
+ // evaluation can run while `lib/ampless.ts` is still in its TDZ
14
+ // because the themes-registry → theme → shim → ampless dependency
15
+ // chain is circular by construction.
16
+ export const listPublishedPosts: typeof ampless.listPublishedPosts =
17
+ (...args) => ampless.listPublishedPosts(...args)
18
+ export const getPublishedPost: typeof ampless.getPublishedPost =
19
+ (...args) => ampless.getPublishedPost(...args)
20
+ export const listPostsByTag: typeof ampless.listPostsByTag =
21
+ (...args) => ampless.listPostsByTag(...args)
14
22
 
15
23
  export type {
16
24
  ListPostsOptions,
@@ -4,5 +4,8 @@
4
4
 
5
5
  import { ampless } from './ampless'
6
6
 
7
- export const postMetadata = ampless.postMetadata.bind(ampless)
8
- export const siteMetadata = ampless.siteMetadata.bind(ampless)
7
+ // Arrow wrappers: defer `ampless` resolution to call time (avoid TDZ).
8
+ export const postMetadata: typeof ampless.postMetadata =
9
+ (...args) => ampless.postMetadata(...args)
10
+ export const siteMetadata: typeof ampless.siteMetadata =
11
+ (...args) => ampless.siteMetadata(...args)
@@ -3,6 +3,9 @@
3
3
 
4
4
  import { ampless } from './ampless'
5
5
 
6
- export const loadSiteSettings = ampless.loadSiteSettings.bind(ampless)
6
+ // Arrow wrapper: defer `ampless` resolution to call time (avoid TDZ in
7
+ // the themes-registry → theme → shim → ampless circular import chain).
8
+ export const loadSiteSettings: typeof ampless.loadSiteSettings =
9
+ (...args) => ampless.loadSiteSettings(...args)
7
10
 
8
11
  export type { EffectiveSiteSettings } from '@ampless/runtime'
@@ -3,5 +3,8 @@
3
3
 
4
4
  import { ampless } from './ampless'
5
5
 
6
- export const publicAssetUrl = ampless.publicAssetUrl.bind(ampless)
7
- export const isStorageConfigured = ampless.isStorageConfigured.bind(ampless)
6
+ // Arrow wrappers: defer `ampless` resolution to call time (avoid TDZ).
7
+ export const publicAssetUrl: typeof ampless.publicAssetUrl =
8
+ (...args) => ampless.publicAssetUrl(...args)
9
+ export const isStorageConfigured: typeof ampless.isStorageConfigured =
10
+ (...args) => ampless.isStorageConfigured(...args)
@@ -3,6 +3,8 @@
3
3
 
4
4
  import { ampless } from './ampless'
5
5
 
6
- export const resolveActiveTheme = ampless.resolveActiveTheme.bind(ampless)
6
+ // Arrow wrapper: defer `ampless` resolution to call time (avoid TDZ).
7
+ export const resolveActiveTheme: typeof ampless.resolveActiveTheme =
8
+ (...args) => ampless.resolveActiveTheme(...args)
7
9
 
8
10
  export type { ResolvedTheme } from '@ampless/runtime'
@@ -3,7 +3,9 @@
3
3
 
4
4
  import { ampless } from './ampless'
5
5
 
6
- export const loadThemeConfig = ampless.loadThemeConfig.bind(ampless)
6
+ // Arrow wrapper: defer `ampless` resolution to call time (avoid TDZ).
7
+ export const loadThemeConfig: typeof ampless.loadThemeConfig =
8
+ (...args) => ampless.loadThemeConfig(...args)
7
9
 
8
10
  export { renderThemeCss } from '@ampless/runtime'
9
11
 
@@ -8,36 +8,39 @@
8
8
  "build": "next build",
9
9
  "start": "next start",
10
10
  "lint": "next lint",
11
- "sandbox": "ampx sandbox"
11
+ "sandbox": "ampx sandbox",
12
+ "sandbox:dev": "ampx sandbox --once && next dev",
13
+ "update-ampless": "npx create-ampless@latest upgrade",
14
+ "copy-theme": "npx create-ampless@latest copy-theme"
12
15
  },
13
16
  "dependencies": {
14
17
  "@aws-amplify/adapter-nextjs": "^1.6.0",
15
18
  "@radix-ui/react-dialog": "^1.1.4",
16
19
  "@radix-ui/react-label": "^2.1.1",
17
20
  "@radix-ui/react-slot": "^1.1.1",
18
- "@tiptap/extension-image": "^2.10.4",
19
- "@tiptap/extension-link": "^2.10.4",
20
- "@tiptap/pm": "^2.10.4",
21
- "@tiptap/react": "^2.10.4",
22
- "@tiptap/starter-kit": "^2.10.4",
23
- "@ampless/plugin-og-image": "^0.2.0-alpha.0",
24
- "@ampless/plugin-rss": "^0.2.0-alpha.0",
25
- "@ampless/plugin-seo": "^0.2.0-alpha.0",
26
- "@ampless/plugin-webhook": "^0.2.0-alpha.0",
27
- "@ampless/admin": "^0.2.0-alpha.0",
28
- "@ampless/backend": "^0.2.0-alpha.0",
29
- "@ampless/runtime": "^0.2.0-alpha.0",
21
+ "@tiptap/extension-image": "^3.23.4",
22
+ "@tiptap/extension-link": "^3.23.4",
23
+ "@tiptap/pm": "^3.23.4",
24
+ "@tiptap/react": "^3.23.4",
25
+ "@tiptap/starter-kit": "^3.23.4",
26
+ "@ampless/plugin-og-image": "^0.2.0-alpha.3",
27
+ "@ampless/plugin-rss": "^0.2.0-alpha.3",
28
+ "@ampless/plugin-seo": "^0.2.0-alpha.3",
29
+ "@ampless/plugin-webhook": "^0.2.0-alpha.3",
30
+ "@ampless/admin": "^0.2.0-alpha.10",
31
+ "@ampless/backend": "^0.2.0-alpha.4",
32
+ "@ampless/runtime": "^0.2.0-alpha.5",
30
33
  "@digital-go-jp/tailwind-theme-plugin": "^0.3.4",
31
- "ampless": "^0.2.0-alpha.0",
34
+ "ampless": "^0.2.0-alpha.3",
32
35
  "aws-amplify": "^6.10.0",
33
36
  "class-variance-authority": "^0.7.1",
34
37
  "clsx": "^2.1.1",
35
- "lucide-react": "^0.469.0",
36
- "next": "^15.1.0",
38
+ "lucide-react": "^1.16.0",
39
+ "next": "^16.2.6",
37
40
  "react": "^19.0.0",
38
41
  "react-dom": "^19.0.0",
39
42
  "react-image-crop": "^11.0.7",
40
- "tailwind-merge": "^2.6.0"
43
+ "tailwind-merge": "^3.6.0"
41
44
  },
42
45
  "devDependencies": {
43
46
  "@aws-amplify/backend": "^1.13.0",
@@ -45,7 +48,7 @@
45
48
  "@aws-sdk/client-appsync": "^3.717.0",
46
49
  "@aws-sdk/client-cognito-identity-provider": "^3.717.0",
47
50
  "@aws-sdk/client-dynamodb": "^3.717.0",
48
- "@aws-sdk/client-s3": "^3.717.0",
51
+ "@aws-sdk/client-s3": "^3.1048.0",
49
52
  "@aws-sdk/client-sqs": "^3.717.0",
50
53
  "@aws-sdk/lib-dynamodb": "^3.717.0",
51
54
  "@aws-sdk/util-dynamodb": "^3.717.0",
@@ -58,6 +61,6 @@
58
61
  "aws-cdk-lib": "^2.174.0",
59
62
  "postcss": "^8.4.0",
60
63
  "tailwindcss": "^4.0.0",
61
- "typescript": "^5.7.0"
64
+ "typescript": "^6.0.3"
62
65
  }
63
66
  }
@@ -0,0 +1,33 @@
1
+ // Public-site proxy (Next.js 16 rename of "middleware"). Implementation
2
+ // moved to `@ampless/runtime` (L1 extraction); this file wires the
3
+ // project's `cms.config` into the factory and re-exports the default
4
+ // matcher. The runtime export name is still `createAmplessMiddleware`
5
+ // for API stability; only the user-side file convention (proxy.ts +
6
+ // `export const proxy`) follows Next 16's rename.
7
+ //
8
+ // See `@ampless/runtime/middleware` for behaviour details: multi-site
9
+ // host rewrite, `<slug>.html` → raw route, `?previewTheme=` header
10
+ // forwarding, multi-site Cache-Control override.
11
+
12
+ import cmsConfig from './cms.config'
13
+ import { createAmplessMiddleware } from '@ampless/runtime/middleware'
14
+
15
+ export const proxy = createAmplessMiddleware({ cmsConfig })
16
+
17
+ // Next.js 16's Turbopack requires `config` to be a statically
18
+ // analysable object literal — referencing an imported variable
19
+ // (e.g. `defaultMatcherConfig` from @ampless/runtime/middleware)
20
+ // causes a build error:
21
+ // "Next.js can't recognize the exported `config` field in route.
22
+ // It needs to be a static object."
23
+ //
24
+ // So we inline the matcher here. If you change it, keep it in sync
25
+ // with `defaultMatcherConfig` documented in @ampless/runtime/middleware.
26
+ // The matcher excludes admin / api / login / static assets /
27
+ // amplify_outputs.json so the public-site proxy doesn't rewrite
28
+ // legitimate non-blog routes.
29
+ export const config = {
30
+ matcher: [
31
+ '/((?!admin|api|login|_next/static|_next/image|favicon\\.ico|amplify_outputs\\.json).*)',
32
+ ],
33
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ampless",
3
- "version": "0.2.0-alpha.0",
3
+ "version": "0.2.0-alpha.10",
4
4
  "description": "Create a new ampless project",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,8 @@
22
22
  "homepage": "https://github.com/heavymoons/ampless#readme",
23
23
  "bugs": "https://github.com/heavymoons/ampless/issues",
24
24
  "dependencies": {
25
- "@clack/prompts": "^0.9.1",
25
+ "@clack/prompts": "^1.4.0",
26
+ "execa": "^9.6.1",
26
27
  "picocolors": "^1.1.1"
27
28
  },
28
29
  "keywords": [
@@ -1,13 +0,0 @@
1
- // Public-site middleware. Implementation moved to `@ampless/runtime`
2
- // (L1 extraction); this file wires the project's `cms.config` into
3
- // the factory and re-exports the default matcher.
4
- //
5
- // See `@ampless/runtime/middleware` for behaviour details: multi-site
6
- // host rewrite, `<slug>.html` → raw route, `?previewTheme=` header
7
- // forwarding, multi-site Cache-Control override.
8
-
9
- import cmsConfig from './cms.config'
10
- import { createAmplessMiddleware, defaultMatcherConfig } from '@ampless/runtime/middleware'
11
-
12
- export const middleware = createAmplessMiddleware({ cmsConfig })
13
- export const config = defaultMatcherConfig