create-varity-app 2.0.0-beta.25 → 2.0.0-beta.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -77,7 +77,7 @@ Or deploy from your AI editor with the [Varity MCP server](https://www.npmjs.com
77
77
 
78
78
  ---
79
79
 
80
- **Part of the [Varity SDK](https://github.com/varity-labs/varity-sdk)** -- Build, deploy, and monetize apps 70% cheaper than AWS.
80
+ **Part of the [Varity SDK](https://github.com/varity-labs/varity-sdk).** Deploy any app, AI agent, or LLM in 60 seconds. 60-80% cheaper than AWS.
81
81
 
82
82
  [Documentation](https://docs.varity.so) | [GitHub](https://github.com/varity-labs/varity-sdk) | [Discord](https://discord.gg/7vWsdwa2Bg)
83
83
 
package/dist/create.js CHANGED
@@ -8,9 +8,9 @@ import { getInstallCommand } from "./utils.js";
8
8
  const __filename = fileURLToPath(import.meta.url);
9
9
  const __dirname = path.dirname(__filename);
10
10
  const WORKSPACE_DEPS = {
11
- "@varity-labs/sdk": "2.0.0-beta.6",
12
- "@varity-labs/types": "2.0.0-beta.4",
13
- "@varity-labs/ui-kit": "2.0.0-beta.7",
11
+ "@varity-labs/sdk": "2.0.0-beta.14",
12
+ "@varity-labs/types": "2.0.0-beta.8",
13
+ "@varity-labs/ui-kit": "2.0.0-beta.15",
14
14
  };
15
15
  const EXCLUDED_FILES = new Set([
16
16
  ".env.local",
@@ -74,11 +74,16 @@ export async function createApp(projectName, packageManager) {
74
74
  return true;
75
75
  },
76
76
  });
77
- // Rename gitignore .gitignore (npm strips .gitignore from tarballs)
78
- const gitignoreSrc = path.join(targetDir, "gitignore");
79
- const gitignoreDst = path.join(targetDir, ".gitignore");
80
- if (fs.existsSync(gitignoreSrc) && !fs.existsSync(gitignoreDst)) {
81
- await fs.rename(gitignoreSrc, gitignoreDst);
77
+ // Rename dotfiles back (npm strips them from tarballs)
78
+ for (const [plain, dot] of [
79
+ ["gitignore", ".gitignore"],
80
+ ["npmrc", ".npmrc"],
81
+ ]) {
82
+ const src = path.join(targetDir, plain);
83
+ const dst = path.join(targetDir, dot);
84
+ if (fs.existsSync(src) && !fs.existsSync(dst)) {
85
+ await fs.rename(src, dst);
86
+ }
82
87
  }
83
88
  // Rewrite package.json
84
89
  const pkgPath = path.join(targetDir, "package.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-varity-app",
3
- "version": "2.0.0-beta.25",
3
+ "version": "2.0.0-beta.26",
4
4
  "description": "Create production-ready apps with auth, database, and payments built in",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -7,7 +7,7 @@
7
7
  # You never need to manually set these values.
8
8
 
9
9
  # Auth (optional — dev credentials used automatically when blank)
10
- NEXT_PUBLIC_PRIVY_APP_ID=
10
+ NEXT_PUBLIC_VARITY_AUTH_APP_ID=
11
11
 
12
12
  # Database (optional — dev database used automatically when blank)
13
13
  NEXT_PUBLIC_VARITY_APP_TOKEN=
@@ -11,7 +11,7 @@
11
11
  | Feature | Status | Notes |
12
12
  |---------|--------|-------|
13
13
  | Landing Page | Working | 6 sections, scroll animations, social proof |
14
- | Auth (Login) | Working | Email/Google via Privy, zero-config dev credentials |
14
+ | Auth (Login) | Working | Email/Google, zero-config dev credentials |
15
15
  | Dashboard | Working | KPI cards, checklist, activity feed |
16
16
  | Projects/Tasks/Team CRUD | Working | Full create, read, update, delete with validation |
17
17
  | Settings | Working | 4 tabs with backend persistence via DB Proxy |
@@ -22,8 +22,8 @@
22
22
 
23
23
  ## Known Issues
24
24
 
25
- ### 1. Auth Uses Privy Directly (Abstraction Coming Post-Beta)
26
- The template uses `usePrivy()` and `NEXT_PUBLIC_PRIVY_APP_ID`. The planned `useAuth()` hook and `NEXT_PUBLIC_VARITY_AUTH_ID` env var are post-beta tasks. No action required -- current auth works correctly.
25
+ ### 1. Auth Provider Configuration
26
+ The template uses `useAuth()` and `NEXT_PUBLIC_VARITY_AUTH_APP_ID`. Auth works correctly out of the box no action required.
27
27
 
28
28
  ### 2. Payments Section is Placeholder
29
29
  Settings > Billing shows mock UI. Credit card payment integration (on/off ramp) is coming soon. Wire your own billing provider (Stripe, etc.) if needed now.
@@ -32,13 +32,13 @@ Settings > Billing shows mock UI. Credit card payment integration (on/off ramp)
32
32
  All pages are statically exported. No SSR, API routes, or middleware. Do not use dynamic routes (`[id]` patterns) -- use client-side state for detail views instead.
33
33
 
34
34
  ### 4. Navigation Flash
35
- Brief "Initializing Dashboard" screen when navigating between pages. Caused by `PrivyReadyGate` re-checking auth state. Resolves in under 1 second.
35
+ Brief "Initializing Dashboard" screen when navigating between pages. Caused by `ReadyGate` re-checking auth state. Resolves in under 1 second.
36
36
 
37
37
  ### 5. Team Email Invites Are Local Only
38
38
  No SMTP integration. Team members are added to the database but no invitation email is sent. Integrate your own email service if needed.
39
39
 
40
40
  ### 6. Sessions and Password Are Auth-Provider Managed
41
- Settings > Security shows mock session data. Password changes and profile photos are managed by the auth provider (Privy), not the template.
41
+ Settings > Security shows mock session data. Password changes and profile photos are managed by the auth provider, not the template.
42
42
 
43
43
  ## Environment
44
44
 
@@ -67,7 +67,7 @@ This template works immediately with **zero setup**:
67
67
 
68
68
  ### Instant Database
69
69
  - ✅ Create, read, update, delete data
70
- - ✅ Dev token built-in
70
+ - ✅ Dev key built-in
71
71
  - ✅ Production-ready proxy
72
72
  - ❌ No credentials needed
73
73
 
@@ -216,7 +216,7 @@ The database collection is created automatically on first use — no migrations
216
216
  | Variable | Required | Notes |
217
217
  |----------|----------|-------|
218
218
  | `NEXT_PUBLIC_VARITY_AUTH_ID` | No | Auth provider (auto-configured) |
219
- | `NEXT_PUBLIC_VARITY_APP_TOKEN` | No | Database token (auto-configured) |
219
+ | `NEXT_PUBLIC_VARITY_APP_TOKEN` | No | Database key (auto-configured) |
220
220
  | `NEXT_PUBLIC_VARITY_APP_ID` | No | App ID (auto-configured) |
221
221
 
222
222
  ## Deployment
@@ -1,5 +1,6 @@
1
1
  /** @type {import('next').NextConfig} */
2
2
  const nextConfig = {
3
+ basePath: process.env.NEXT_PUBLIC_BASE_PATH || '',
3
4
  output: 'export',
4
5
  images: { unoptimized: true },
5
6
  trailingSlash: true,
package/template/npmrc ADDED
@@ -0,0 +1 @@
1
+ legacy-peer-deps=true
@@ -26,6 +26,10 @@
26
26
  "react": "^18.3.0",
27
27
  "react-dom": "^18.3.0"
28
28
  },
29
+ "overrides": {
30
+ "postcss": "$postcss",
31
+ "typescript": "^5.0.0"
32
+ },
29
33
  "devDependencies": {
30
34
  "@playwright/test": "^1.58.2",
31
35
  "@types/node": "^20.0.0",
@@ -33,7 +37,7 @@
33
37
  "@types/react-dom": "^18.3.0",
34
38
  "autoprefixer": "^10.0.0",
35
39
  "husky": "^9.1.7",
36
- "postcss": "^8.0.0",
40
+ "postcss": "^8.4.31",
37
41
  "tailwindcss": "^3.4.0",
38
42
  "typescript": "^5.0.0"
39
43
  }
@@ -7,22 +7,22 @@ import { useProjects, useTasks, useTeam } from '@/lib/hooks';
7
7
  import { CommandPalette } from '@varity-labs/ui-kit';
8
8
  import { Menu, X } from 'lucide-react';
9
9
 
10
- // Defensively import Privy/UI-Kit components at runtime (not statically) so the
10
+ // Defensively import UI-Kit components at runtime (not statically) so the
11
11
  // dashboard renders gracefully even if @varity-labs/ui-kit hasn't been installed
12
12
  // yet (e.g. during local scaffolding before `npm install` completes).
13
13
  // This is intentional — it is NOT a sign that something is broken.
14
14
  // See KNOWN_ISSUES.md for details on this pattern.
15
15
  let DashboardLayout: any = null;
16
- let PrivyProtectedRoute: any = null;
17
- let PrivyStackComponent: any = null;
18
- let usePrivyHook: any = null;
16
+ let ProtectedRouteComponent: any = null;
17
+ let AuthProviderComponent: any = null;
18
+ let useAuthHook: any = null;
19
19
 
20
20
  try {
21
21
  const uiKit = require('@varity-labs/ui-kit');
22
22
  DashboardLayout = uiKit.DashboardLayout;
23
- PrivyProtectedRoute = uiKit.PrivyProtectedRoute;
24
- PrivyStackComponent = uiKit.PrivyStack;
25
- usePrivyHook = uiKit.usePrivy;
23
+ ProtectedRouteComponent = uiKit.ProtectedRoute;
24
+ AuthProviderComponent = uiKit.AuthProvider;
25
+ useAuthHook = uiKit.useAuth;
26
26
  } catch {
27
27
  // ui-kit not installed or not yet available — DashboardShell fallback renders below
28
28
  }
@@ -117,8 +117,8 @@ function MobileNav({
117
117
 
118
118
  function DashboardShell({ children }: { children: React.ReactNode }) {
119
119
  // eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
120
- const privy = usePrivyHook ? usePrivyHook() : { user: null, logout: async () => {} };
121
- const { user, logout } = privy;
120
+ const auth = useAuthHook ? useAuthHook() : { user: null, logout: async () => {} };
121
+ const { user, logout } = auth;
122
122
  const pathname = usePathname();
123
123
  const router = useRouter();
124
124
  const isMobile = useIsMobile();
@@ -283,21 +283,21 @@ export default function DashboardRootLayout({
283
283
  }: {
284
284
  children: React.ReactNode;
285
285
  }) {
286
- // Always wrap in PrivyStack + PrivyProtectedRoute - uses dev credentials automatically when env vars are empty
287
- if (!PrivyProtectedRoute || !PrivyStackComponent) {
286
+ // Always wrap in AuthProvider + ProtectedRoute - uses dev credentials automatically when env vars are empty
287
+ if (!ProtectedRouteComponent || !AuthProviderComponent) {
288
288
  // Fallback if ui-kit package isn't installed
289
289
  return <DashboardShell>{children}</DashboardShell>;
290
290
  }
291
291
 
292
292
  return (
293
- <PrivyStackComponent
294
- appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID}
293
+ <AuthProviderComponent
294
+ appId={process.env.NEXT_PUBLIC_VARITY_AUTH_APP_ID}
295
295
  loginMethods={['email', 'google']}
296
296
  appearance={{ theme: 'light', accentColor: '#2563EB', logo: '/logo.svg' }}
297
297
  >
298
- <PrivyProtectedRoute fallback={<RedirectToLogin />}>
298
+ <ProtectedRouteComponent fallback={<RedirectToLogin />}>
299
299
  <DashboardShell>{children}</DashboardShell>
300
- </PrivyProtectedRoute>
301
- </PrivyStackComponent>
300
+ </ProtectedRouteComponent>
301
+ </AuthProviderComponent>
302
302
  );
303
303
  }
@@ -37,15 +37,15 @@ import {
37
37
  Key,
38
38
  } from 'lucide-react';
39
39
 
40
- const privyAppId = process.env.NEXT_PUBLIC_PRIVY_APP_ID;
40
+ const authAppId = process.env.NEXT_PUBLIC_VARITY_AUTH_APP_ID;
41
41
 
42
- let PrivyUserProfile: any = null;
43
- let usePrivyHook: any = null;
42
+ let UserProfileComponent: any = null;
43
+ let useAuthHook: any = null;
44
44
 
45
45
  try {
46
46
  const uiKit = require('@varity-labs/ui-kit');
47
- PrivyUserProfile = uiKit.PrivyUserProfile;
48
- usePrivyHook = uiKit.usePrivy;
47
+ UserProfileComponent = uiKit.UserProfile;
48
+ useAuthHook = uiKit.useAuth;
49
49
  } catch {}
50
50
 
51
51
  const TABS = [
@@ -79,7 +79,7 @@ export default function SettingsPage() {
79
79
  const { settings, loading, update: updateSettings } = useUserSettings();
80
80
  const toast = useToast();
81
81
  // eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() + env var, stable across renders
82
- const privy = privyAppId && usePrivyHook ? usePrivyHook() : { logout: async () => {} };
82
+ const auth = authAppId && useAuthHook ? useAuthHook() : { logout: async () => {} };
83
83
 
84
84
  const [activeTab, setActiveTab] = useState<TabId>('general');
85
85
 
@@ -112,7 +112,7 @@ export default function SettingsPage() {
112
112
  },
113
113
  ]);
114
114
 
115
- // Sync profile form when Privy data arrives asynchronously
115
+ // Sync profile form when auth data arrives asynchronously
116
116
  useEffect(() => {
117
117
  if (name || email) {
118
118
  setProfileForm({ name: name || '', email: email || '' });
@@ -557,13 +557,13 @@ export default function SettingsPage() {
557
557
  </div>
558
558
 
559
559
  {/* Account Settings */}
560
- {privyAppId && PrivyUserProfile && (
560
+ {authAppId && UserProfileComponent && (
561
561
  <div className="rounded-xl border border-gray-200 bg-white p-6 shadow-sm">
562
562
  <h2 className="mb-4 text-lg font-semibold text-gray-900 flex items-center gap-2">
563
563
  <Key className="h-5 w-5" />
564
564
  Account Settings
565
565
  </h2>
566
- <PrivyUserProfile showLogoutButton={false} />
566
+ <UserProfileComponent showLogoutButton={false} />
567
567
  </div>
568
568
  )}
569
569
 
@@ -577,7 +577,7 @@ export default function SettingsPage() {
577
577
  These actions are permanent and cannot be undone.
578
578
  </p>
579
579
  <div className="flex flex-wrap gap-3">
580
- <Button variant="danger" onClick={() => privy.logout()}>
580
+ <Button variant="danger" onClick={() => auth.logout()}>
581
581
  <LogOut className="h-4 w-4" />
582
582
  Sign Out
583
583
  </Button>
@@ -1,19 +1,22 @@
1
1
  import type { Metadata } from 'next';
2
+ import { APP_NAME } from '@/lib/constants';
2
3
  import { Providers } from '@/components/providers';
3
4
  import './globals.css';
4
5
 
6
+ const appTitle = `${APP_NAME} - Dashboard`;
7
+
5
8
  export const metadata: Metadata = {
6
- title: 'TaskFlow - Project Management',
9
+ title: appTitle,
7
10
  description: 'Manage projects, track tasks, and collaborate with your team.',
8
11
  metadataBase: new URL('https://example.com'),
9
12
  openGraph: {
10
- title: 'TaskFlow - Project Management',
13
+ title: appTitle,
11
14
  description: 'Manage projects, track tasks, and collaborate with your team.',
12
15
  type: 'website',
13
16
  },
14
17
  twitter: {
15
18
  card: 'summary',
16
- title: 'TaskFlow - Project Management',
19
+ title: appTitle,
17
20
  description: 'Manage projects, track tasks, and collaborate with your team.',
18
21
  },
19
22
  };
@@ -6,29 +6,29 @@ import Link from 'next/link';
6
6
  import { CheckCircle } from 'lucide-react';
7
7
  import { APP_NAME } from '@/lib/constants';
8
8
 
9
- let PrivyStackComponent: any = null;
10
- let usePrivyHook: (() => { authenticated: boolean; ready: boolean; login: () => void }) | null = null;
9
+ let AuthProviderComponent: any = null;
10
+ let useAuthHook: (() => { authenticated: boolean; ready: boolean; login: () => void }) | null = null;
11
11
 
12
12
  try {
13
13
  const uiKit = require('@varity-labs/ui-kit');
14
- PrivyStackComponent = uiKit.PrivyStack;
15
- usePrivyHook = uiKit.usePrivy;
14
+ AuthProviderComponent = uiKit.AuthProvider;
15
+ useAuthHook = uiKit.useAuth;
16
16
  } catch {}
17
17
 
18
18
  function LoginContent() {
19
19
  const router = useRouter();
20
20
  // eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
21
- const privy = usePrivyHook ? usePrivyHook() : null;
21
+ const auth = useAuthHook ? useAuthHook() : null;
22
22
 
23
23
  useEffect(() => {
24
- if (privy?.authenticated) {
24
+ if (auth?.authenticated) {
25
25
  router.push('/dashboard');
26
26
  }
27
- }, [privy?.authenticated, router]);
27
+ }, [auth?.authenticated, router]);
28
28
 
29
29
  const handleLogin = () => {
30
- if (privy?.login) {
31
- privy.login();
30
+ if (auth?.login) {
31
+ auth.login();
32
32
  }
33
33
  };
34
34
 
@@ -49,15 +49,15 @@ function LoginContent() {
49
49
  </div>
50
50
 
51
51
  <div className="rounded-xl border border-gray-200 bg-white p-8 shadow-sm">
52
- {privy ? (
52
+ {auth ? (
53
53
  <button
54
54
  onClick={handleLogin}
55
- disabled={!privy.ready || privy.authenticated}
55
+ disabled={!auth.ready || auth.authenticated}
56
56
  className="w-full px-6 py-3 bg-primary-600 hover:bg-primary-700 disabled:bg-gray-300 disabled:cursor-not-allowed text-white font-medium rounded-lg transition-colors shadow-sm"
57
57
  >
58
- {!privy.ready
58
+ {!auth.ready
59
59
  ? 'Loading...'
60
- : privy.authenticated
60
+ : auth.authenticated
61
61
  ? 'Already Signed In'
62
62
  : 'Sign In with Email or Social'}
63
63
  </button>
@@ -79,16 +79,16 @@ function LoginContent() {
79
79
  }
80
80
 
81
81
  export default function LoginPage() {
82
- // Always wrap in PrivyStack - it uses dev credentials automatically when no appId is provided
83
- if (PrivyStackComponent) {
82
+ // Always wrap in AuthProvider - it uses dev credentials automatically when no appId is provided
83
+ if (AuthProviderComponent) {
84
84
  return (
85
- <PrivyStackComponent
86
- appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID}
85
+ <AuthProviderComponent
86
+ appId={process.env.NEXT_PUBLIC_VARITY_AUTH_APP_ID}
87
87
  loginMethods={['email', 'google']}
88
88
  appearance={{ theme: 'light', accentColor: '#2563EB', logo: '/logo.svg' }}
89
89
  >
90
90
  <LoginContent />
91
- </PrivyStackComponent>
91
+ </AuthProviderComponent>
92
92
  );
93
93
  }
94
94
 
@@ -5,7 +5,7 @@ import { ToastProvider } from '@varity-labs/ui-kit';
5
5
 
6
6
  export function Providers({ children }: { children: ReactNode }) {
7
7
  // Only ToastProvider at the global level.
8
- // PrivyStack is added in dashboard/layout.tsx and login/page.tsx —
8
+ // AuthProvider is added in dashboard/layout.tsx and login/page.tsx —
9
9
  // the landing page loads instantly without any auth dependency.
10
10
  return <ToastProvider>{children}</ToastProvider>;
11
11
  }
@@ -4,18 +4,18 @@ import { useState, useEffect, useCallback } from 'react';
4
4
  import { projects, tasks, teamMembers, userSettings } from './database';
5
5
  import type { Project, Task, TeamMember, UserSettings } from '../types';
6
6
 
7
- let usePrivyHook: any = null;
7
+ let useAuthHook: any = null;
8
8
  try {
9
9
  const uiKit = require('@varity-labs/ui-kit');
10
- usePrivyHook = uiKit.usePrivy;
10
+ useAuthHook = uiKit.useAuth;
11
11
  } catch {}
12
12
 
13
13
  export function useCurrentUser() {
14
14
  // eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on require() success, stable across renders
15
- const privy = usePrivyHook ? usePrivyHook() : { user: null, authenticated: false, logout: async () => {} };
15
+ const auth = useAuthHook ? useAuthHook() : { user: null, authenticated: false, logout: async () => {} };
16
16
 
17
- // Extract email from any Privy auth method (email, Google, GitHub, etc.)
18
- const user = privy.user;
17
+ // Extract email from any auth method (email, Google, GitHub, etc.)
18
+ const user = auth.user;
19
19
  const email =
20
20
  user?.email?.address ||
21
21
  user?.google?.email ||
@@ -30,8 +30,8 @@ export function useCurrentUser() {
30
30
  id: user?.id || 'dev-user-id',
31
31
  email,
32
32
  name,
33
- authenticated: privy.authenticated,
34
- logout: privy.logout,
33
+ authenticated: auth.authenticated,
34
+ logout: auth.logout,
35
35
  };
36
36
  }
37
37