create-nextly-app 0.0.2-alpha.1 → 0.0.2-alpha.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 (40) hide show
  1. package/dist/cli.cjs +1 -1
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.mjs +1 -1
  4. package/dist/cli.mjs.map +1 -1
  5. package/package.json +4 -4
  6. package/templates/base/.env.example +16 -0
  7. package/templates/base/README.md +30 -0
  8. package/templates/base/eslint.config.mjs +18 -0
  9. package/templates/base/next.config.ts +21 -0
  10. package/templates/base/postcss.config.mjs +7 -0
  11. package/templates/base/public/file.svg +1 -0
  12. package/templates/base/public/globe.svg +1 -0
  13. package/templates/base/public/next.svg +1 -0
  14. package/templates/base/public/vercel.svg +1 -0
  15. package/templates/base/public/window.svg +1 -0
  16. package/templates/base/src/app/admin/[[...params]]/layout.tsx +20 -0
  17. package/templates/base/src/app/admin/[[...params]]/page.tsx +27 -0
  18. package/templates/base/src/app/admin/api/[[...params]]/route.ts +12 -0
  19. package/templates/base/src/app/api/health/route.ts +7 -0
  20. package/templates/base/src/app/api/media/[[...path]]/route.ts +34 -0
  21. package/templates/base/src/app/favicon.ico +0 -0
  22. package/templates/base/src/app/globals.css +55 -0
  23. package/templates/base/src/app/layout.tsx +43 -0
  24. package/templates/base/src/app/page.tsx +65 -0
  25. package/templates/base/src/types/generated/.gitkeep +0 -0
  26. package/templates/base/src/types/generated/nextly-types.ts +12 -0
  27. package/templates/base/tsconfig.json +35 -0
  28. package/templates/blank/.env.example +8 -0
  29. package/templates/blank/README.md +63 -0
  30. package/templates/blank/nextly.config.ts +14 -0
  31. package/templates/blank/src/access/README.md +22 -0
  32. package/templates/blank/src/app/(frontend)/page.tsx +176 -0
  33. package/templates/blank/src/app/globals.css +79 -0
  34. package/templates/blank/src/app/layout.tsx +46 -0
  35. package/templates/blank/src/collections/README.md +22 -0
  36. package/templates/blank/src/components/README.md +10 -0
  37. package/templates/blank/src/components/ThemeToggle.tsx +113 -0
  38. package/templates/blank/src/lib/README.md +15 -0
  39. package/templates/blank/src/singles/README.md +19 -0
  40. package/templates/blank/template.json +14 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nextly-app",
3
- "version": "0.0.2-alpha.1",
3
+ "version": "0.0.2-alpha.2",
4
4
  "description": "CLI to scaffold Nextly in your Next.js project",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -42,9 +42,9 @@
42
42
  "typescript": "^5.9.3",
43
43
  "vite-tsconfig-paths": "^5.1.4",
44
44
  "vitest": "^4.0.8",
45
- "@nextlyhq/eslint-config": "0.0.2-alpha.0",
46
- "@nextlyhq/telemetry": "0.0.2-alpha.0",
47
- "@nextlyhq/tsconfig": "0.0.2-alpha.0"
45
+ "@nextlyhq/eslint-config": "0.0.2-alpha.1",
46
+ "@nextlyhq/telemetry": "0.0.2-alpha.1",
47
+ "@nextlyhq/tsconfig": "0.0.2-alpha.1"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=20.0.0"
@@ -0,0 +1,16 @@
1
+ # Nextly Configuration
2
+ # Generated by create-nextly-app
3
+
4
+ # Database Configuration
5
+ DB_DIALECT={{databaseDialect}}
6
+ DATABASE_URL={{databaseUrl}}
7
+
8
+ # Authentication (REQUIRED)
9
+ # Generate with: openssl rand -base64 32
10
+ NEXTLY_SECRET=change-me-generate-a-secure-secret
11
+
12
+ # Application URL
13
+ NEXT_PUBLIC_APP_URL=http://localhost:3000
14
+
15
+ # Storage Configuration
16
+ {{storageEnvVars}}
@@ -0,0 +1,30 @@
1
+ # Base template
2
+
3
+ Shared scaffolding for all `create-nextly-app` templates. The CLI applies this template first, then overlays the user-selected template (`blank`, `blog`, or future) on top.
4
+
5
+ > Not user-selectable. You will not see "base" in the CLI menu. It is always applied beneath your chosen template.
6
+
7
+ ## What's in here
8
+
9
+ - Admin route handler stub (`app/admin/[[...params]]/page.tsx`)
10
+ - Default API handler stubs
11
+ - Shared styles and Tailwind preset wiring
12
+ - Default `tsconfig.json`, `next.config.ts`, `eslint.config.mjs`, `postcss.config.mjs`
13
+
14
+ ## Maintainer notes
15
+
16
+ When editing files in `base/`, run the CLI against `--template blank` and `--template blog` locally to confirm both still scaffold cleanly:
17
+
18
+ ```bash
19
+ pnpm --filter create-nextly-app dev -- my-test \
20
+ --template blank \
21
+ --local-template ./templates \
22
+ --skip-install
23
+
24
+ pnpm --filter create-nextly-app dev -- my-test \
25
+ --template blog \
26
+ --local-template ./templates \
27
+ --skip-install
28
+ ```
29
+
30
+ See [CONTRIBUTING.md](../../CONTRIBUTING.md).
@@ -0,0 +1,18 @@
1
+ import { defineConfig, globalIgnores } from "eslint/config";
2
+ import nextVitals from "eslint-config-next/core-web-vitals";
3
+ import nextTs from "eslint-config-next/typescript";
4
+
5
+ const eslintConfig = defineConfig([
6
+ ...nextVitals,
7
+ ...nextTs,
8
+ // Override default ignores of eslint-config-next.
9
+ globalIgnores([
10
+ // Default ignores of eslint-config-next:
11
+ ".next/**",
12
+ "out/**",
13
+ "build/**",
14
+ "next-env.d.ts",
15
+ ]),
16
+ ]);
17
+
18
+ export default eslintConfig;
@@ -0,0 +1,21 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ serverExternalPackages: [
5
+ "nextly",
6
+ "@nextlyhq/adapter-drizzle",
7
+ "@nextlyhq/adapter-postgres",
8
+ "@nextlyhq/adapter-mysql",
9
+ "@nextlyhq/adapter-sqlite",
10
+ "drizzle-orm",
11
+ "drizzle-kit",
12
+ "pg",
13
+ "mysql2",
14
+ "better-sqlite3",
15
+ "bcryptjs",
16
+ "sharp",
17
+ "esbuild",
18
+ ],
19
+ };
20
+
21
+ export default nextConfig;
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
6
+
7
+ export default config;
@@ -0,0 +1 @@
1
+ <svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
@@ -0,0 +1 @@
1
+ <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
@@ -0,0 +1,20 @@
1
+ import { getBrandingCss } from "nextly/config";
2
+
3
+ import config from "../../../../nextly.config";
4
+
5
+ const brandingCss = getBrandingCss(config.admin?.branding);
6
+
7
+ export default function AdminLayout({
8
+ children,
9
+ }: {
10
+ children: React.ReactNode;
11
+ }) {
12
+ return (
13
+ <>
14
+ {brandingCss && (
15
+ <style dangerouslySetInnerHTML={{ __html: brandingCss }} />
16
+ )}
17
+ {children}
18
+ </>
19
+ );
20
+ }
@@ -0,0 +1,27 @@
1
+ "use client";
2
+
3
+ // Plugin-side admin imports. Every scaffold ships @nextlyhq/plugin-form-builder
4
+ // as a dependency (see packages/create-nextly-app utils/template.ts). These
5
+ // three lines register the plugin's custom admin field components and load its
6
+ // CSS so the Forms collection's drag-and-drop field builder and Submissions
7
+ // filter UI render correctly. Without them, Forms still appears in the sidebar
8
+ // but the builder falls back to plain JSON/text inputs.
9
+ import "@nextlyhq/admin/style.css";
10
+ import "@nextlyhq/plugin-form-builder/admin";
11
+ import "@nextlyhq/plugin-form-builder/styles/builder.css";
12
+ import "@nextlyhq/plugin-form-builder/styles/submissions-filter.css";
13
+ import { RootLayout, QueryProvider, ErrorBoundary } from "@nextlyhq/admin";
14
+
15
+ export default function AdminPage() {
16
+ return (
17
+ <ErrorBoundary
18
+ onError={(error, errorInfo) => {
19
+ console.error("Admin error:", error, errorInfo);
20
+ }}
21
+ >
22
+ <QueryProvider>
23
+ <RootLayout />
24
+ </QueryProvider>
25
+ </ErrorBoundary>
26
+ );
27
+ }
@@ -0,0 +1,12 @@
1
+ import { createDynamicHandlers } from "nextly/runtime";
2
+
3
+ import nextlyConfig from "../../../../../nextly.config";
4
+
5
+ const handlers = createDynamicHandlers({ config: nextlyConfig });
6
+
7
+ export const GET = handlers.GET;
8
+ export const POST = handlers.POST;
9
+ export const PUT = handlers.PUT;
10
+ export const PATCH = handlers.PATCH;
11
+ export const DELETE = handlers.DELETE;
12
+ export const OPTIONS = handlers.OPTIONS;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Health Check Endpoint
3
+ *
4
+ * GET /api/health - Check if the API is running
5
+ */
6
+
7
+ export { GET, HEAD } from "nextly/api/health";
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Media API Routes (Catch-All Handler)
3
+ *
4
+ * This single route handles all media operations:
5
+ *
6
+ * Media Files:
7
+ * - GET /api/media - List media with pagination
8
+ * - POST /api/media - Upload new media file
9
+ * - GET /api/media/:id - Get media by ID
10
+ * - PATCH /api/media/:id - Update media metadata
11
+ * - DELETE /api/media/:id - Delete media file
12
+ * - PATCH /api/media/:id/move - Move media to folder
13
+ *
14
+ * Folders:
15
+ * - GET /api/media/folders - List folders
16
+ * - POST /api/media/folders - Create folder
17
+ * - GET /api/media/folders/:id - Get folder by ID
18
+ * - PATCH /api/media/folders/:id - Update folder
19
+ * - DELETE /api/media/folders/:id - Delete folder
20
+ * - GET /api/media/folders/:id/contents - Get folder contents
21
+ * - GET /api/media/folders/root/contents - Get root folder contents
22
+ */
23
+
24
+ import { createMediaHandlers } from "nextly/api/media-handlers";
25
+
26
+ import nextlyConfig from "../../../../../nextly.config";
27
+
28
+ // Pass config to ensure storage plugins work across all worker processes
29
+ const handlers = createMediaHandlers({ config: nextlyConfig });
30
+
31
+ export const GET = handlers.GET;
32
+ export const POST = handlers.POST;
33
+ export const PATCH = handlers.PATCH;
34
+ export const DELETE = handlers.DELETE;
@@ -0,0 +1,55 @@
1
+ @import "tailwindcss";
2
+
3
+ :root {
4
+ --background: #ffffff;
5
+ --foreground: #171717;
6
+ }
7
+
8
+ @theme inline {
9
+ --color-background: var(--background);
10
+ --color-foreground: var(--foreground);
11
+ --font-sans: var(--font-geist-sans);
12
+ --font-mono: var(--font-geist-mono);
13
+ }
14
+
15
+ @media (prefers-color-scheme: dark) {
16
+ :root {
17
+ --background: #0a0a0a;
18
+ --foreground: #ededed;
19
+ }
20
+ }
21
+
22
+ body {
23
+ background: var(--background);
24
+ color: var(--foreground);
25
+ font-family: Arial, Helvetica, sans-serif;
26
+ }
27
+
28
+ /* ===============================================================
29
+ Accessibility baseline
30
+ ---------------------------------------------------------------
31
+ Applied globally so the template passes a WCAG AA keyboard audit
32
+ out of the box. Adjust to match your brand.
33
+ =============================================================== */
34
+
35
+ /* Visible focus ring for keyboard users. `:focus-visible` only fires
36
+ on keyboard / programmatic focus, so clicking a button doesn't
37
+ show the ring but tabbing to it does. */
38
+ *:focus-visible {
39
+ outline: 2px solid currentColor;
40
+ outline-offset: 2px;
41
+ border-radius: 2px;
42
+ }
43
+
44
+ /* Honor OS-level reduced-motion preference — disables hover scale,
45
+ transitions, and animations for users who've opted out. */
46
+ @media (prefers-reduced-motion: reduce) {
47
+ *,
48
+ *::before,
49
+ *::after {
50
+ animation-duration: 0.01ms !important;
51
+ animation-iteration-count: 1 !important;
52
+ transition-duration: 0.01ms !important;
53
+ scroll-behavior: auto !important;
54
+ }
55
+ }
@@ -0,0 +1,43 @@
1
+ import type { Metadata } from "next";
2
+ import { Geist, Geist_Mono } from "next/font/google";
3
+ import "./globals.css";
4
+
5
+ const geistSans = Geist({
6
+ variable: "--font-geist-sans",
7
+ subsets: ["latin"],
8
+ });
9
+
10
+ const geistMono = Geist_Mono({
11
+ variable: "--font-geist-mono",
12
+ subsets: ["latin"],
13
+ });
14
+
15
+ /**
16
+ * `metadataBase` tells Next.js how to resolve relative URLs in OpenGraph
17
+ * images, Twitter images, and canonical URLs. Set `NEXT_PUBLIC_SITE_URL`
18
+ * in your environment to your production domain (e.g.
19
+ * `https://yourblog.com`). The localhost fallback keeps dev working.
20
+ */
21
+ export const metadata: Metadata = {
22
+ metadataBase: new URL(
23
+ process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000"
24
+ ),
25
+ title: { default: "Nextly", template: "%s — Nextly" },
26
+ description: "A site built with Nextly.",
27
+ };
28
+
29
+ export default function RootLayout({
30
+ children,
31
+ }: Readonly<{
32
+ children: React.ReactNode;
33
+ }>) {
34
+ return (
35
+ <html lang="en" suppressHydrationWarning>
36
+ <body
37
+ className={`${geistSans.variable} ${geistMono.variable} antialiased`}
38
+ >
39
+ {children}
40
+ </body>
41
+ </html>
42
+ );
43
+ }
@@ -0,0 +1,65 @@
1
+ import Image from "next/image";
2
+
3
+ export default function Home() {
4
+ return (
5
+ <div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
6
+ <main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
7
+ <Image
8
+ className="dark:invert"
9
+ src="/next.svg"
10
+ alt="Next.js logo"
11
+ width={100}
12
+ height={20}
13
+ priority
14
+ />
15
+ <div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
16
+ <h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
17
+ To get started, edit the page.tsx file.
18
+ </h1>
19
+ <p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
20
+ Looking for a starting point or more instructions? Head over to{" "}
21
+ <a
22
+ href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
23
+ className="font-medium text-zinc-950 dark:text-zinc-50"
24
+ >
25
+ Templates
26
+ </a>{" "}
27
+ or the{" "}
28
+ <a
29
+ href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
30
+ className="font-medium text-zinc-950 dark:text-zinc-50"
31
+ >
32
+ Learning
33
+ </a>{" "}
34
+ center.
35
+ </p>
36
+ </div>
37
+ <div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
38
+ <a
39
+ className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
40
+ href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
41
+ target="_blank"
42
+ rel="noopener noreferrer"
43
+ >
44
+ <Image
45
+ className="dark:invert"
46
+ src="/vercel.svg"
47
+ alt="Vercel logomark"
48
+ width={16}
49
+ height={16}
50
+ />
51
+ Deploy Now
52
+ </a>
53
+ <a
54
+ className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
55
+ href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
56
+ target="_blank"
57
+ rel="noopener noreferrer"
58
+ >
59
+ Documentation
60
+ </a>
61
+ </div>
62
+ </main>
63
+ </div>
64
+ );
65
+ }
File without changes
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Nextly Generated Types
3
+ *
4
+ * This file will be auto-generated when you run:
5
+ * npx nextly dev
6
+ * npx nextly generate:types
7
+ *
8
+ * Do not edit this file manually - it will be overwritten.
9
+ */
10
+
11
+ // Types will be generated here after running nextly dev
12
+ export {};
@@ -0,0 +1,35 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./src/*"],
23
+ "@nextly-config": ["./nextly.config.ts"]
24
+ }
25
+ },
26
+ "include": [
27
+ "next-env.d.ts",
28
+ "**/*.ts",
29
+ "**/*.tsx",
30
+ ".next/types/**/*.ts",
31
+ ".next/dev/types/**/*.ts",
32
+ "**/*.mts"
33
+ ],
34
+ "exclude": ["node_modules"]
35
+ }
@@ -0,0 +1,8 @@
1
+ # Public site URL used by:
2
+ # - Metadata API (canonical URLs, OpenGraph image resolution)
3
+ # - sitemap.xml, robots.txt, and any RSS feed route handlers you add
4
+ # - JSON-LD structured data links
5
+ #
6
+ # Set this to your production domain when deploying (e.g. https://yourapp.com).
7
+ # The localhost fallback keeps local development working.
8
+ NEXT_PUBLIC_SITE_URL=http://localhost:3000
@@ -0,0 +1,63 @@
1
+ # Blank template
2
+
3
+ A minimal Nextly project with the conventional folder layout already
4
+ scaffolded. Empty `nextly.config.ts`, no collections, one landing
5
+ page, and READMEs in every convention folder so you know where things
6
+ go as you grow.
7
+
8
+ ## When to use
9
+
10
+ Choose `blank` when you want to build everything from scratch but
11
+ appreciate having the right folder structure waiting for you. Pick
12
+ [`blog`](../blog/README.md) instead if you want a populated example
13
+ with collections, singles, frontend pages, RSS, search, and demo
14
+ content already wired up.
15
+
16
+ ## Scaffold
17
+
18
+ ```bash
19
+ pnpm create nextly-app@alpha my-app --template blank
20
+ ```
21
+
22
+ ## What you get
23
+
24
+ ```
25
+ my-app/
26
+ ├── nextly.config.ts # Empty config — add your collections / singles
27
+ ├── .env.example # NEXT_PUBLIC_SITE_URL etc.
28
+ ├── next.config.ts # (inherited from base)
29
+ ├── postcss.config.mjs # (inherited from base)
30
+ ├── tsconfig.json # (inherited from base)
31
+ └── src/
32
+ ├── access/ # RBAC functions (anyone, authenticated, ...)
33
+ ├── collections/ # defineCollection() definitions
34
+ ├── singles/ # defineSingle() definitions
35
+ ├── components/ # React components (ThemeToggle ships as an example)
36
+ ├── lib/ # Project-wide helpers
37
+ └── app/
38
+ ├── layout.tsx # Root layout (font + metadata)
39
+ ├── globals.css # Design tokens
40
+ └── (frontend)/ # Public-facing routes (route group)
41
+ └── page.tsx # Landing page — flips between "Set up admin" / "Open admin"
42
+ ```
43
+
44
+ The `(frontend)` route group keeps your public pages cleanly separated
45
+ from `app/admin/...` and `app/api/...` routes that Nextly mounts. As
46
+ you add routes, drop them inside `(frontend)/` and they'll inherit
47
+ your blog/marketing layout instead of the admin's.
48
+
49
+ Every convention folder ships with a `README.md` explaining what
50
+ belongs there. Replace them with real code as you build.
51
+
52
+ ## Next steps
53
+
54
+ - **Add a collection** — create `src/collections/Posts.ts`, register
55
+ it in `nextly.config.ts`, run `pnpm dev`. The admin will surface it
56
+ immediately.
57
+ - **Add a public page** — drop a new file under
58
+ `src/app/(frontend)/blog/page.tsx`. It'll be live at `/blog`.
59
+ - **Configure storage / email** — see
60
+ [`nextlyhq.com/docs`](https://nextlyhq.com/docs) for adapter setup.
61
+
62
+ See [`templates/blog/README.md`](../blog/README.md) for a fully
63
+ populated example showing all of the above wired up.
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from "nextly/config";
2
+
3
+ export default defineConfig({
4
+ // Add your collections here
5
+ collections: [],
6
+
7
+ // Add your singles (globals) here
8
+ singles: [],
9
+
10
+ // TypeScript type generation
11
+ typescript: {
12
+ outputFile: "./src/types/generated/nextly-types.ts",
13
+ },
14
+ });
@@ -0,0 +1,22 @@
1
+ # Access
2
+
3
+ Access-control functions used by `defineCollection({ access: ... })`
4
+ and `defineSingle({ access: ... })`. Each function decides whether the
5
+ current user can perform an action (read, create, update, delete) on a
6
+ collection or single.
7
+
8
+ Conventions:
9
+
10
+ - One function per file. File name matches the function name.
11
+ - Export the function as a named export.
12
+ - Type signature: `AccessControlFunction` from `nextly`.
13
+
14
+ Common patterns shipped in the blog template (for reference):
15
+
16
+ - `anyone.ts` — always allow (use for public reads).
17
+ - `authenticated.ts` — require any logged-in user.
18
+ - `is-admin.ts` — require the `admin` role.
19
+ - `is-author-or-editor.ts` — require one of several roles.
20
+
21
+ Add your own here as your project grows. Wire them up in your
22
+ collections / singles config.