create-questpie 1.0.0 → 2.0.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 (41) hide show
  1. package/README.md +20 -12
  2. package/dist/index.mjs +9 -2
  3. package/package.json +21 -21
  4. package/templates/tanstack-start/AGENTS.md +366 -318
  5. package/templates/tanstack-start/CLAUDE.md +84 -52
  6. package/templates/tanstack-start/README.md +59 -52
  7. package/templates/tanstack-start/components.json +20 -20
  8. package/templates/tanstack-start/package.json +6 -0
  9. package/templates/tanstack-start/questpie.config.ts +7 -7
  10. package/templates/tanstack-start/src/lib/auth-client.ts +3 -3
  11. package/templates/tanstack-start/src/lib/client.ts +13 -0
  12. package/templates/tanstack-start/src/lib/env.ts +19 -22
  13. package/templates/tanstack-start/src/lib/query-client.ts +5 -5
  14. package/templates/tanstack-start/src/questpie/admin/admin.ts +8 -4
  15. package/templates/tanstack-start/src/questpie/server/.generated/factories.ts +318 -0
  16. package/templates/tanstack-start/src/questpie/server/.generated/index.ts +153 -0
  17. package/templates/tanstack-start/src/questpie/server/app.ts +10 -52
  18. package/templates/tanstack-start/src/questpie/server/collections/posts.collection.ts +39 -53
  19. package/templates/tanstack-start/src/questpie/server/config/admin.ts +83 -0
  20. package/templates/tanstack-start/src/questpie/server/config/auth.ts +8 -0
  21. package/templates/tanstack-start/src/questpie/server/config/openapi.ts +10 -0
  22. package/templates/tanstack-start/src/questpie/server/globals/site-settings.global.ts +9 -14
  23. package/templates/tanstack-start/src/questpie/server/modules.ts +10 -0
  24. package/templates/tanstack-start/src/questpie/server/questpie.config.ts +20 -0
  25. package/templates/tanstack-start/src/router.tsx +6 -5
  26. package/templates/tanstack-start/src/routes/__root.tsx +11 -9
  27. package/templates/tanstack-start/src/routes/admin/$.tsx +14 -13
  28. package/templates/tanstack-start/src/routes/admin/index.tsx +11 -10
  29. package/templates/tanstack-start/src/routes/admin/login.tsx +11 -10
  30. package/templates/tanstack-start/src/routes/admin.tsx +53 -52
  31. package/templates/tanstack-start/src/routes/api/{cms/$.ts → $.ts} +6 -20
  32. package/templates/tanstack-start/src/styles.css +109 -109
  33. package/templates/tanstack-start/tsconfig.json +27 -25
  34. package/templates/tanstack-start/vite.config.ts +5 -3
  35. package/templates/tanstack-start/src/lib/cms-client.ts +0 -12
  36. package/templates/tanstack-start/src/migrations/index.ts +0 -8
  37. package/templates/tanstack-start/src/questpie/admin/builder.ts +0 -4
  38. package/templates/tanstack-start/src/questpie/server/builder.ts +0 -4
  39. package/templates/tanstack-start/src/questpie/server/dashboard.ts +0 -68
  40. package/templates/tanstack-start/src/questpie/server/rpc.ts +0 -4
  41. package/templates/tanstack-start/src/questpie/server/sidebar.ts +0 -26
@@ -0,0 +1,83 @@
1
+ import { adminConfig } from "#questpie/factories";
2
+
3
+ export default adminConfig({
4
+ branding: {
5
+ name: "{{projectName}}",
6
+ },
7
+ sidebar: {
8
+ sections: [
9
+ {
10
+ id: "main",
11
+ title: "Content",
12
+ items: [
13
+ {
14
+ type: "link",
15
+ label: "Dashboard",
16
+ href: "/admin",
17
+ icon: { type: "icon", props: { name: "ph:house" } },
18
+ },
19
+ { type: "collection", collection: "posts" },
20
+ { type: "global", global: "siteSettings" },
21
+ ],
22
+ },
23
+ ],
24
+ },
25
+ dashboard: {
26
+ title: "Dashboard",
27
+ description: "Overview of your content",
28
+ columns: 4,
29
+ sections: [
30
+ { id: "content", label: "Content", layout: "grid", columns: 2 },
31
+ { id: "recent", label: "Recent", layout: "grid", columns: 4 },
32
+ ],
33
+ items: [
34
+ {
35
+ sectionId: "content",
36
+ id: "total-posts",
37
+ type: "stats",
38
+ collection: "posts",
39
+ label: "Total Posts",
40
+ span: 1,
41
+ },
42
+ {
43
+ sectionId: "content",
44
+ id: "published-posts",
45
+ type: "stats",
46
+ collection: "posts",
47
+ label: "Published",
48
+ filter: { published: true },
49
+ variant: "primary",
50
+ span: 1,
51
+ },
52
+ {
53
+ sectionId: "recent",
54
+ id: "recent-posts",
55
+ type: "recentItems",
56
+ collection: "posts",
57
+ label: "Recent Posts",
58
+ limit: 5,
59
+ span: 2,
60
+ },
61
+ {
62
+ sectionId: "recent",
63
+ id: "quick-actions",
64
+ type: "quickActions",
65
+ label: "Quick Actions",
66
+ actions: [
67
+ {
68
+ label: "New Post",
69
+ action: { type: "create", collection: "posts" },
70
+ },
71
+ {
72
+ label: "Site Settings",
73
+ action: {
74
+ type: "link",
75
+ href: "/admin/globals/siteSettings",
76
+ },
77
+ },
78
+ ],
79
+ span: 2,
80
+ },
81
+ ],
82
+ },
83
+ });
@@ -0,0 +1,8 @@
1
+ import { authConfig } from "questpie";
2
+
3
+ export default authConfig({
4
+ emailAndPassword: {
5
+ enabled: true,
6
+ requireEmailVerification: false,
7
+ },
8
+ });
@@ -0,0 +1,10 @@
1
+ import { openApiConfig } from "@questpie/openapi";
2
+
3
+ export default openApiConfig({
4
+ info: {
5
+ title: "{{projectName}} API",
6
+ version: "1.0.0",
7
+ description: "QUESTPIE API",
8
+ },
9
+ scalar: { theme: "purple" },
10
+ });
@@ -1,24 +1,19 @@
1
- import { qb } from "@/questpie/server/builder.js";
1
+ import { global } from "#questpie/factories";
2
2
 
3
- export const siteSettings = qb
4
- .global("site_settings")
5
- .fields((f) => ({
6
- siteName: f.text({
7
- label: "Site Name",
8
- required: true,
9
- default: "{{projectName}}",
10
- }),
11
- description: f.textarea({
12
- label: "Site Description",
13
- default: "A QUESTPIE CMS powered site",
14
- }),
3
+ export const siteSettings = global("site_settings")
4
+ .fields(({ f }) => ({
5
+ siteName: f.text().label("Site Name").required().default("{{projectName}}"),
6
+ description: f
7
+ .textarea()
8
+ .label("Site Description")
9
+ .default("A QUESTPIE powered site"),
15
10
  }))
16
11
  .admin(({ c }) => ({
17
12
  label: "Site Settings",
18
13
  icon: c.icon("ph:gear"),
19
14
  }))
20
15
  .form(({ v, f }) =>
21
- v.form({
16
+ v.globalForm({
22
17
  fields: [f.siteName, f.description],
23
18
  }),
24
19
  );
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Modules — static module dependencies for this project.
3
+ */
4
+ import { adminModule } from "@questpie/admin/server";
5
+ import { openApiModule } from "@questpie/openapi";
6
+
7
+ export default [
8
+ adminModule,
9
+ openApiModule,
10
+ ] as const;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * QUESTPIE Runtime Configuration
3
+ *
4
+ * Runtime-only configuration: database, adapters, secrets.
5
+ * Entity definitions (collections, globals, etc.) are codegen-generated.
6
+ * Sidebar, dashboard, branding are file conventions.
7
+ */
8
+
9
+ import { ConsoleAdapter, runtimeConfig } from "questpie";
10
+
11
+ import { env } from "@/lib/env.js";
12
+
13
+ export default runtimeConfig({
14
+ app: { url: env.APP_URL },
15
+ db: { url: env.DATABASE_URL },
16
+ storage: { basePath: "/api" },
17
+ email: {
18
+ adapter: new ConsoleAdapter({ logHtml: false }),
19
+ },
20
+ });
@@ -1,10 +1,11 @@
1
1
  import { createRouter } from "@tanstack/react-router";
2
+
2
3
  import { routeTree } from "./routeTree.gen";
3
4
 
4
5
  export function getRouter() {
5
- return createRouter({
6
- routeTree,
7
- scrollRestoration: true,
8
- defaultPreloadStaleTime: 0,
9
- });
6
+ return createRouter({
7
+ routeTree,
8
+ scrollRestoration: true,
9
+ defaultPreloadStaleTime: 0,
10
+ });
10
11
  }
@@ -1,16 +1,18 @@
1
+ import "virtual:iconify-preload";
2
+
1
3
  import { createRootRoute } from "@tanstack/react-router";
2
4
 
3
5
  export const Route = createRootRoute({
4
- head: () => ({
5
- meta: [
6
- { charSet: "utf-8" },
7
- { name: "viewport", content: "width=device-width, initial-scale=1" },
8
- { title: "{{projectName}}" },
9
- ],
10
- }),
11
- shellComponent: RootDocument,
6
+ head: () => ({
7
+ meta: [
8
+ { charSet: "utf-8" },
9
+ { name: "viewport", content: "width=device-width, initial-scale=1" },
10
+ { title: "{{projectName}}" },
11
+ ],
12
+ }),
13
+ shellComponent: RootDocument,
12
14
  });
13
15
 
14
16
  function RootDocument({ children }: { children: React.ReactNode }) {
15
- return <>{children}</>;
17
+ return <>{children}</>;
16
18
  }
@@ -1,21 +1,22 @@
1
- import { AdminRouter } from "@questpie/admin/client";
2
1
  import { createFileRoute, useNavigate } from "@tanstack/react-router";
3
2
 
3
+ import { AdminRouter } from "@questpie/admin/client";
4
+
4
5
  function AdminCatchAll() {
5
- const navigate = useNavigate();
6
- const params = Route.useParams();
7
- const splat = params._splat as string;
8
- const segments = splat ? splat.split("/").filter(Boolean) : [];
6
+ const navigate = useNavigate();
7
+ const params = Route.useParams();
8
+ const splat = params._splat as string;
9
+ const segments = splat ? splat.split("/").filter(Boolean) : [];
9
10
 
10
- return (
11
- <AdminRouter
12
- segments={segments}
13
- navigate={(path) => navigate({ to: path })}
14
- basePath="/admin"
15
- />
16
- );
11
+ return (
12
+ <AdminRouter
13
+ segments={segments}
14
+ navigate={(path) => navigate({ to: path })}
15
+ basePath="/admin"
16
+ />
17
+ );
17
18
  }
18
19
 
19
20
  export const Route = createFileRoute("/admin/$")({
20
- component: AdminCatchAll,
21
+ component: AdminCatchAll,
21
22
  });
@@ -1,18 +1,19 @@
1
- import { AdminRouter } from "@questpie/admin/client";
2
1
  import { createFileRoute, useNavigate } from "@tanstack/react-router";
3
2
 
3
+ import { AdminRouter } from "@questpie/admin/client";
4
+
4
5
  function AdminDashboard() {
5
- const navigate = useNavigate();
6
+ const navigate = useNavigate();
6
7
 
7
- return (
8
- <AdminRouter
9
- segments={[]}
10
- navigate={(path) => navigate({ to: path })}
11
- basePath="/admin"
12
- />
13
- );
8
+ return (
9
+ <AdminRouter
10
+ segments={[]}
11
+ navigate={(path) => navigate({ to: path })}
12
+ basePath="/admin"
13
+ />
14
+ );
14
15
  }
15
16
 
16
17
  export const Route = createFileRoute("/admin/")({
17
- component: AdminDashboard,
18
+ component: AdminDashboard,
18
19
  });
@@ -1,17 +1,18 @@
1
- import { LoginPage } from "@questpie/admin/client";
2
1
  import { createFileRoute } from "@tanstack/react-router";
3
2
 
3
+ import { LoginPage } from "@questpie/admin/client";
4
+
4
5
  export const Route = createFileRoute("/admin/login")({
5
- component: AdminLoginPage,
6
+ component: AdminLoginPage,
6
7
  });
7
8
 
8
9
  function AdminLoginPage() {
9
- return (
10
- <LoginPage
11
- title="Welcome back"
12
- description="Sign in to access admin panel"
13
- showForgotPassword={false}
14
- showSignUp={false}
15
- />
16
- );
10
+ return (
11
+ <LoginPage
12
+ title="Welcome back"
13
+ description="Sign in to access admin panel"
14
+ showForgotPassword={false}
15
+ showSignUp={false}
16
+ />
17
+ );
17
18
  }
@@ -1,68 +1,69 @@
1
- import { AdminLayoutProvider } from "@questpie/admin/client";
2
1
  import {
3
- createFileRoute,
4
- HeadContent,
5
- Link,
6
- Outlet,
7
- Scripts,
8
- useLocation,
2
+ createFileRoute,
3
+ HeadContent,
4
+ Link,
5
+ Outlet,
6
+ Scripts,
7
+ useLocation,
9
8
  } from "@tanstack/react-router";
10
- import { authClient } from "~/lib/auth-client";
11
- import { client } from "~/lib/cms-client";
12
- import { queryClient } from "~/lib/query-client";
13
- import { admin } from "~/questpie/admin/admin";
9
+
10
+ import { authClient } from "@/lib/auth-client";
11
+ import { client } from "@/lib/client";
12
+ import { queryClient } from "@/lib/query-client";
13
+ import { admin } from "@/questpie/admin/admin";
14
+ import { AdminLayoutProvider } from "@questpie/admin/client";
14
15
 
15
16
  import adminCss from "../admin.css?url";
16
17
 
17
18
  function AdminLink({
18
- to,
19
- className,
20
- children,
21
- activeProps,
19
+ to,
20
+ className,
21
+ children,
22
+ activeProps,
22
23
  }: {
23
- to: string;
24
- className?: string;
25
- children: React.ReactNode;
26
- activeProps?: { className?: string };
24
+ to: string;
25
+ className?: string;
26
+ children: React.ReactNode;
27
+ activeProps?: { className?: string };
27
28
  }) {
28
- return (
29
- <Link to={to} className={className} activeProps={activeProps}>
30
- {children}
31
- </Link>
32
- );
29
+ return (
30
+ <Link to={to} className={className} activeProps={activeProps}>
31
+ {children}
32
+ </Link>
33
+ );
33
34
  }
34
35
 
35
36
  export const Route = createFileRoute("/admin")({
36
- head: () => ({
37
- title: "Admin Panel",
38
- links: [{ rel: "stylesheet", href: adminCss }],
39
- }),
40
- component: AdminLayout,
37
+ head: () => ({
38
+ title: "Admin Panel",
39
+ links: [{ rel: "stylesheet", href: adminCss }],
40
+ }),
41
+ component: AdminLayout,
41
42
  });
42
43
 
43
44
  function AdminLayout() {
44
- const location = useLocation();
45
+ const location = useLocation();
45
46
 
46
- return (
47
- <html lang="en" className="dark">
48
- <head>
49
- <HeadContent />
50
- </head>
51
- <body>
52
- <AdminLayoutProvider
53
- admin={admin}
54
- client={client}
55
- queryClient={queryClient}
56
- authClient={authClient}
57
- LinkComponent={AdminLink}
58
- activeRoute={location.pathname}
59
- basePath="/admin"
60
- useServerTranslations
61
- >
62
- <Outlet />
63
- </AdminLayoutProvider>
64
- <Scripts />
65
- </body>
66
- </html>
67
- );
47
+ return (
48
+ <html lang="en" className="dark">
49
+ <head>
50
+ <HeadContent />
51
+ </head>
52
+ <body>
53
+ <AdminLayoutProvider
54
+ admin={admin}
55
+ client={client}
56
+ queryClient={queryClient}
57
+ authClient={authClient}
58
+ LinkComponent={AdminLink}
59
+ activeRoute={location.pathname}
60
+ basePath="/admin"
61
+ useServerTranslations
62
+ >
63
+ <Outlet />
64
+ </AdminLayoutProvider>
65
+ <Scripts />
66
+ </body>
67
+ </html>
68
+ );
68
69
  }
@@ -1,25 +1,11 @@
1
- import { withOpenApi } from "@questpie/openapi";
2
1
  import { createFileRoute } from "@tanstack/react-router";
3
2
  import { createFetchHandler } from "questpie";
4
- import { appRpc, cms } from "@/questpie/server/app.js";
5
3
 
6
- const handler = withOpenApi(
7
- createFetchHandler(cms, {
8
- basePath: "/api/cms",
9
- rpc: appRpc,
10
- }),
11
- {
12
- cms,
13
- rpc: appRpc,
14
- basePath: "/api/cms",
15
- info: {
16
- title: "{{projectName}} API",
17
- version: "1.0.0",
18
- description: "QUESTPIE CMS API",
19
- },
20
- scalar: { theme: "purple" },
21
- },
22
- );
4
+ import { app } from "@/questpie/server/app.js";
5
+
6
+ const handler = createFetchHandler(app, {
7
+ basePath: "/api",
8
+ });
23
9
 
24
10
  const handleCmsRequest = async (request: Request) => {
25
11
  const response = await handler(request);
@@ -32,7 +18,7 @@ const handleCmsRequest = async (request: Request) => {
32
18
  );
33
19
  };
34
20
 
35
- export const Route = createFileRoute("/api/cms/$")({
21
+ export const Route = createFileRoute("/api/$")({
36
22
  server: {
37
23
  handlers: {
38
24
  GET: ({ request }) => handleCmsRequest(request),