@newt-app/templates 0.0.2 → 0.1.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.
package/dist/index.js CHANGED
@@ -11,16 +11,16 @@ var package_json_default = {
11
11
  "build": "turbo run build",
12
12
  "dev": "turbo run dev",
13
13
  "lint": "turbo run lint",
14
+ "test": "turbo run test",
14
15
  "format": "prettier --write \\"**/*.{ts,tsx,js,jsx,json,md,yaml,yml}\\"",
15
16
  "format:check": "prettier --check \\"**/*.{ts,tsx,js,jsx,json,md,yaml,yml}\\"",
16
- "check-types": "turbo run check-types",
17
17
  "db:migrate": "turbo run migrate",
18
18
  "db:generate": "turbo run generate"
19
19
  },
20
20
  "devDependencies": {
21
21
  "prettier": "^3.7.4",
22
22
  "turbo": "^2.8.16",
23
- "typescript": "5.9.2"
23
+ "typescript": "6.0.2"
24
24
  },
25
25
  "packageManager": "pnpm@9.0.0",
26
26
  "engines": {
@@ -113,10 +113,12 @@ var turbo_json_default = {
113
113
  "outputs": [".next/**", "!.next/cache/**"]
114
114
  },
115
115
  "lint": {
116
- "dependsOn": ["^lint"]
116
+ "dependsOn": ["^lint"],
117
+ "env": ["NODE_ENV"]
117
118
  },
118
- "check-types": {
119
- "dependsOn": ["^check-types"]
119
+ "test": {
120
+ "dependsOn": ["^build"],
121
+ "outputs": ["coverage/**"]
120
122
  },
121
123
  "dev": {
122
124
  "cache": false,
@@ -166,10 +168,10 @@ Open [http://localhost:3000](http://localhost:3000).
166
168
 
167
169
  ## Packages
168
170
 
169
- - **\`@repo/auth\`** \u2014 better-auth config
170
- - **\`@repo/ui\`** \u2014 shared React components
171
- - **\`@repo/eslint-config\`** \u2014 shared ESLint config
172
- - **\`@repo/typescript-config\`** \u2014 shared tsconfig
171
+ - **\`@<%= projectName %>/auth\`** \u2014 better-auth config
172
+ - **\`@<%= projectName %>/ui\`** \u2014 shared React components
173
+ - **\`@<%= projectName %>/eslint-config\`** \u2014 shared ESLint config
174
+ - **\`@<%= projectName %>/typescript-config\`** \u2014 shared tsconfig
173
175
  `
174
176
  };
175
177
 
@@ -209,30 +211,29 @@ var package_json_default2 = {
209
211
  "dev": "next dev --port 3000",
210
212
  "build": "next build",
211
213
  "start": "next start",
212
- "lint": "eslint --max-warnings 0",
213
- "check-types": "next typegen && tsc --noEmit",
214
+ "lint": "eslint --max-warnings 0 && next typegen && tsc --noEmit",
214
215
  "db:migrate": "better-auth migrate"
215
216
  },
216
217
  "dependencies": {
217
- "@repo/auth": "workspace:*",
218
- "@repo/ui": "workspace:*",
218
+ "@<%= projectName %>/auth": "workspace:*",
219
+ "@<%= projectName %>/ui": "workspace:*",
219
220
  "@tailwindcss/postcss": "^4.2.1",
220
221
  "@tanstack/react-form": "^1.28.5",
221
222
  "@tanstack/react-query": "^5.90.21",
222
223
  "better-auth": "^1.2.8",
223
- "next": "16.1.5",
224
- "react": "^19.2.0",
225
- "react-dom": "^19.2.0",
224
+ "next": "16.2.1",
225
+ "react": "^19.2.4",
226
+ "react-dom": "^19.2.4",
226
227
  "tailwindcss": "^4.2.1"
227
228
  },
228
229
  "devDependencies": {
229
- "@repo/eslint-config": "workspace:*",
230
- "@repo/typescript-config": "workspace:*",
230
+ "@<%= projectName %>/eslint-config": "workspace:*",
231
+ "@<%= projectName %>/typescript-config": "workspace:*",
231
232
  "@types/node": "^22.15.3",
232
- "@types/react": "19.2.2",
233
- "@types/react-dom": "19.2.2",
233
+ "@types/react": "19.2.14",
234
+ "@types/react-dom": "19.2.3",
234
235
  "eslint": "^9.39.1",
235
- "typescript": "5.9.2"
236
+ "typescript": "6.0.2"
236
237
  }
237
238
  }`
238
239
  };
@@ -322,7 +323,7 @@ Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/bui
322
323
  // src/web/templates/eslint-config.ts
323
324
  var eslint_config_default = {
324
325
  filename: "apps/web/eslint.config.js",
325
- template: `import { nextJsConfig } from "@repo/eslint-config/next-js";
326
+ template: `import { nextJsConfig } from "@<%= projectName %>/eslint-config/next-js";
326
327
 
327
328
  /** @type {import("eslint").Linter.Config[]} */
328
329
  export default nextJsConfig;`
@@ -350,27 +351,24 @@ export default nextConfig;`
350
351
  // src/web/templates/postcss-config.ts
351
352
  var postcss_config_default = {
352
353
  filename: "apps/web/postcss.config.mjs",
353
- template: `const config = {
354
- plugins: {
355
- "@tailwindcss/postcss": {},
356
- },
357
- };
358
-
359
- export default config;`
354
+ template: `export { default } from "@<%= projectName %>/ui/postcss.config";`
360
355
  };
361
356
 
362
357
  // src/web/templates/tsconfig.ts
363
358
  var tsconfig_default = {
364
359
  filename: "apps/web/tsconfig.json",
365
360
  template: `{
366
- "extends": "@repo/typescript-config/nextjs.json",
361
+ "extends": "@<%= projectName %>/typescript-config/nextjs.json",
367
362
  "compilerOptions": {
368
363
  "plugins": [
369
364
  {
370
365
  "name": "next"
371
366
  }
372
367
  ],
373
- "strictNullChecks": true
368
+ "strictNullChecks": true,
369
+ "paths": {
370
+ "@/*": ["./*"]
371
+ }
374
372
  },
375
373
  "include": [
376
374
  "**/*.ts",
@@ -383,34 +381,13 @@ var tsconfig_default = {
383
381
  }`
384
382
  };
385
383
 
386
- // src/web/templates/globals-css.ts
387
- var globals_css_default = {
388
- filename: "apps/web/app/globals.css",
389
- template: `@import 'tailwindcss';
390
-
391
- html,
392
- body {
393
- height: 100%;
394
- }
395
-
396
- body {
397
- color: #374151;
398
- background-color: #ffffff;
399
- -webkit-font-smoothing: antialiased;
400
- }
401
-
402
- * {
403
- @apply border-gray-200;
404
- }`
405
- };
406
-
407
384
  // src/web/templates/layout.ts
408
385
  var layout_default = {
409
386
  filename: "apps/web/app/layout.tsx",
410
387
  template: `import type { Metadata } from "next";
411
388
  import localFont from "next/font/local";
412
- import Providers from "./providers";
413
- import "./globals.css";
389
+ import Providers from "@/app/providers";
390
+ import "@<%= projectName %>/ui/globals.css";
414
391
 
415
392
  const geistSans = localFont({
416
393
  src: "./fonts/GeistVF.woff",
@@ -424,6 +401,13 @@ const geistMono = localFont({
424
401
  export const metadata: Metadata = {
425
402
  title: "<%= projectName %>",
426
403
  description: "Next + Nest = Newt",
404
+ icons: {
405
+ icon: [
406
+ { url: "/icon0.svg", type: "image/svg+xml" },
407
+ { url: "/icon1.png", type: "image/png" },
408
+ ],
409
+ apple: "/apple-icon.png",
410
+ },
427
411
  };
428
412
 
429
413
  export default function RootLayout({
@@ -433,7 +417,7 @@ export default function RootLayout({
433
417
  }>) {
434
418
  return (
435
419
  <html lang="en">
436
- <body className={\`\${geistSans.variable} \${geistMono.variable}\`}>
420
+ <body className={\`\${geistSans.variable} \${geistMono.variable} h-full\`}>
437
421
  <Providers>{children}</Providers>
438
422
  </body>
439
423
  </html>
@@ -447,10 +431,11 @@ var page_default = {
447
431
  template: `'use client';
448
432
 
449
433
  import { useQuery } from '@tanstack/react-query';
450
- import { authClient } from '../lib/auth-client';
451
- import { AuthForm } from './auth-form';
452
- import { Link } from '@repo/ui/link';
453
- import { TodoList } from './todo-list';
434
+ import { authClient } from '@/lib/auth-client';
435
+ import { AuthForm } from '@/app/auth-form';
436
+ import { Link } from '@<%= projectName %>/ui/link';
437
+ import { Logo } from '@<%= projectName %>/ui/logo';
438
+ import { TodoList } from '@/app/todo-list';
454
439
 
455
440
  export default function Home() {
456
441
  const { data: session, isPending } = authClient.useSession();
@@ -461,45 +446,46 @@ export default function Home() {
461
446
  });
462
447
 
463
448
  return (
464
- <main className="max-w-lg mx-auto border-r border-l h-full">
449
+ <main className="max-w-lg mx-auto border-r border-l min-h-full">
465
450
  <div className="border-b p-4">
466
451
  <p className="font-mono">apps/web/page.tsx</p>
467
- <p className="text-gray-500">Delete me to get started!</p>
452
+ <p className="text-gray-400">Delete me to get started!</p>
468
453
  </div>
469
454
  <div className="border-b p-4">
470
- <h1 className="text-5xl font-black tracking-tight bg-linear-to-r from-indigo-500 via-purple-500 to-pink-500 bg-clip-text text-transparent">
471
- <%= projectName %>
472
- </h1>
473
- <p className="mt-2 text-sm text-gray-500 tracking-widest uppercase">
455
+ <div className="flex items-center gap-3 pb-2">
456
+ <Logo className="w-10 h-auto text-foreground" />
457
+ <h1 className="text-5xl font-black tracking-tight">
458
+ <%= projectName %>
459
+ </h1>
460
+ </div>
461
+ <p className="mt-2 text-sm text-gray-400 tracking-widest uppercase">
474
462
  Next + Nest = Newt \u{1F49C}
475
463
  </p>
476
- <p className="text-gray-500">The perfect TypeScript monorepo setup</p>
464
+ <p className="text-gray-400">The perfect TypeScript monorepo setup</p>
477
465
  </div>
478
- <div className="border-b p-4 text-gray-500">
479
- <div className="flex justify-end text-gray-500">
480
- <h2 className="uppercase">Next.js</h2>
466
+ <div className="border-b p-4">
467
+ <div className="flex justify-end text-gray-400 uppercase">
468
+ <h2>next.js</h2>
481
469
  </div>
482
470
  <p className="font-mono">apps/web/layout.tsx</p>
483
- <p>Next.js rendering</p>
471
+ <p className="text-gray-400">Next.js rendering</p>
484
472
  </div>
485
473
 
486
474
  <div className="p-4 border-b">
487
- <div className="flex justify-end text-gray-500">
488
- <h2 className="uppercase">Nest</h2>
475
+ <div className="flex justify-end text-gray-400 uppercase">
476
+ <h2>nest.js</h2>
489
477
  </div>
490
- <span className="font-mono text-gray-500 text-xs">
491
- HTTP GET /api/hello
492
- </span>
493
- <pre className="border p-2 rounded bg-gray-50">
478
+ <p className="font-mono">GET /api/hello</p>
479
+ <pre className="mt-2 border rounded-md p-3 text-sm bg-neutral-800">
494
480
  <code>{JSON.stringify(hello, null, 2)}</code>
495
481
  </pre>
496
482
  </div>
497
483
  <div className="p-4 border-b">
498
- <div className="flex justify-end text-gray-500">
484
+ <div className="flex justify-end text-gray-400 uppercase">
499
485
  <h2>better-auth</h2>
500
486
  </div>
501
487
  {isPending ? (
502
- <p className="text-sm text-gray-500">Loading\u2026</p>
488
+ <p className="text-sm text-gray-400">Loading\u2026</p>
503
489
  ) : session ? (
504
490
  <TodoList session={session} />
505
491
  ) : (
@@ -546,10 +532,11 @@ var auth_form_default = {
546
532
 
547
533
  import { useForm } from '@tanstack/react-form';
548
534
  import { useState } from 'react';
549
- import { authClient } from '../lib/auth-client';
535
+ import { authClient } from '@/lib/auth-client';
536
+ import { Button } from '@<%= projectName %>/ui/button';
550
537
 
551
538
  export function AuthForm() {
552
- const [tab, setTab] = useState<'signin' | 'signup'>('signin');
539
+ const [tab, setTab] = useState<'signin' | 'signup'>('signup');
553
540
  const [error, setError] = useState('');
554
541
 
555
542
  const form = useForm({
@@ -570,25 +557,25 @@ export function AuthForm() {
570
557
  <>
571
558
  <div className="flex gap-2 mb-6 text-sm">
572
559
  <button
573
- onClick={() => setTab('signin')}
560
+ onClick={() => setTab('signup')}
574
561
  className={
575
- tab === 'signin'
562
+ tab === 'signup'
576
563
  ? 'font-semibold'
577
- : 'text-gray-500 hover:text-gray-700'
564
+ : 'text-gray-400 hover:text-gray-200'
578
565
  }
579
566
  >
580
- Sign in
567
+ Sign up
581
568
  </button>
582
- <span className="text-gray-200">|</span>
569
+ <span className="text-gray-600">|</span>
583
570
  <button
584
- onClick={() => setTab('signup')}
571
+ onClick={() => setTab('signin')}
585
572
  className={
586
- tab === 'signup'
573
+ tab === 'signin'
587
574
  ? 'font-semibold'
588
- : 'text-gray-500 hover:text-gray-700'
575
+ : 'text-gray-400 hover:text-gray-200'
589
576
  }
590
577
  >
591
- Sign up
578
+ Sign in
592
579
  </button>
593
580
  </div>
594
581
 
@@ -609,7 +596,7 @@ export function AuthForm() {
609
596
  value={field.state.value}
610
597
  onChange={(e) => field.handleChange(e.target.value)}
611
598
  required
612
- className="w-full border border-gray-200 rounded px-3 py-2 text-sm"
599
+ className="flex h-9 w-full rounded-md border border-neutral-700 bg-neutral-800/50 px-3 py-1 text-sm shadow-xs transition-[color,box-shadow] outline-none placeholder:text-neutral-500 focus-visible:border-neutral-500 focus-visible:ring-2 focus-visible:ring-neutral-500/20"
613
600
  />
614
601
  </div>
615
602
  )}
@@ -625,7 +612,7 @@ export function AuthForm() {
625
612
  value={field.state.value}
626
613
  onChange={(e) => field.handleChange(e.target.value)}
627
614
  required
628
- className="w-full border border-gray-200 rounded px-3 py-2 text-sm"
615
+ className="flex h-9 w-full rounded-md border border-neutral-700 bg-neutral-800/50 px-3 py-1 text-sm shadow-xs transition-[color,box-shadow] outline-none placeholder:text-neutral-500 focus-visible:border-neutral-500 focus-visible:ring-2 focus-visible:ring-neutral-500/20"
629
616
  />
630
617
  </div>
631
618
  )}
@@ -641,7 +628,7 @@ export function AuthForm() {
641
628
  onChange={(e) => field.handleChange(e.target.value)}
642
629
  required
643
630
  minLength={8}
644
- className="w-full border border-gray-200 rounded px-3 py-2 text-sm"
631
+ className="flex h-9 w-full rounded-md border border-neutral-700 bg-neutral-800/50 px-3 py-1 text-sm shadow-xs transition-[color,box-shadow] outline-none placeholder:text-neutral-500 focus-visible:border-neutral-500 focus-visible:ring-2 focus-visible:ring-neutral-500/20"
645
632
  />
646
633
  </div>
647
634
  )}
@@ -651,17 +638,13 @@ export function AuthForm() {
651
638
 
652
639
  <form.Subscribe selector={(s) => s.isSubmitting}>
653
640
  {(isSubmitting) => (
654
- <button
655
- type="submit"
656
- disabled={isSubmitting}
657
- className="w-full bg-gray-900 text-white rounded py-2 text-sm font-medium hover:bg-gray-700 disabled:opacity-40"
658
- >
641
+ <Button type="submit" disabled={isSubmitting} className="w-full">
659
642
  {isSubmitting
660
643
  ? 'Loading\u2026'
661
644
  : tab === 'signin'
662
645
  ? 'Sign in'
663
646
  : 'Create account'}
664
- </button>
647
+ </Button>
665
648
  )}
666
649
  </form.Subscribe>
667
650
  </form>
@@ -677,7 +660,8 @@ var todo_list_default = {
677
660
 
678
661
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
679
662
  import { useForm } from '@tanstack/react-form';
680
- import { authClient } from '../lib/auth-client';
663
+ import { authClient } from '@/lib/auth-client';
664
+ import { Button } from '@<%= projectName %>/ui/button';
681
665
 
682
666
  interface Todo {
683
667
  id: number;
@@ -739,10 +723,10 @@ export function TodoList({
739
723
  <>
740
724
  <div className="flex items-center justify-between mb-8">
741
725
  <h1 className="text-2xl font-semibold">Todos</h1>
742
- <div className="flex items-center gap-3 text-sm text-gray-500">
726
+ <div className="flex items-center gap-3 text-sm text-gray-400">
743
727
  <span>{session.user.email}</span>
744
728
  <button
745
- className="hover:text-gray-900"
729
+ className="hover:text-gray-100"
746
730
  onClick={() => authClient.signOut()}
747
731
  >
748
732
  Sign out
@@ -763,28 +747,24 @@ export function TodoList({
763
747
  value={field.state.value}
764
748
  onChange={(e) => field.handleChange(e.target.value)}
765
749
  placeholder="New todo\u2026"
766
- className="flex-1 border border-gray-200 rounded px-3 py-2 text-sm"
750
+ className="flex h-9 flex-1 rounded-md border border-neutral-700 bg-neutral-800/50 px-3 py-1 text-sm shadow-xs transition-[color,box-shadow] outline-none placeholder:text-neutral-500 focus-visible:border-neutral-500 focus-visible:ring-2 focus-visible:ring-neutral-500/20"
767
751
  />
768
752
  )}
769
753
  </form.Field>
770
754
 
771
755
  <form.Subscribe selector={(s) => s.isSubmitting}>
772
756
  {(isSubmitting) => (
773
- <button
774
- type="submit"
775
- disabled={isSubmitting || createMutation.isPending}
776
- className="bg-gray-900 text-white rounded px-4 py-2 text-sm hover:bg-gray-700 disabled:opacity-40"
777
- >
757
+ <Button type="submit" disabled={isSubmitting || createMutation.isPending}>
778
758
  Add
779
- </button>
759
+ </Button>
780
760
  )}
781
761
  </form.Subscribe>
782
762
  </form>
783
763
 
784
764
  {isPending ? (
785
- <p className="text-sm text-gray-500">Loading\u2026</p>
765
+ <p className="text-sm text-gray-400">Loading\u2026</p>
786
766
  ) : (
787
- <ul className="divide-y divide-gray-100">
767
+ <ul className="divide-y divide-neutral-700">
788
768
  {todos.map((todo) => (
789
769
  <li key={todo.id} className="flex items-center gap-3 py-3">
790
770
  <input
@@ -793,13 +773,13 @@ export function TodoList({
793
773
  onChange={() => toggleMutation.mutate(todo.id)}
794
774
  />
795
775
  <span
796
- className={\`flex-1 text-sm \${todo.done ? 'line-through text-gray-500' : ''}\`}
776
+ className={\`flex-1 text-sm \${todo.done ? 'line-through text-gray-400' : ''}\`}
797
777
  >
798
778
  {todo.title}
799
779
  </span>
800
780
  <button
801
781
  onClick={() => deleteMutation.mutate(todo.id)}
802
- className="text-gray-300 hover:text-red-400 text-lg leading-none"
782
+ className="text-gray-600 hover:text-red-400 text-lg leading-none"
803
783
  >
804
784
  \xD7
805
785
  </button>
@@ -809,7 +789,7 @@ export function TodoList({
809
789
  )}
810
790
 
811
791
  {!isPending && todos.length === 0 && (
812
- <p className="text-sm text-gray-500">No todos yet.</p>
792
+ <p className="text-sm text-gray-400">No todos yet.</p>
813
793
  )}
814
794
  </>
815
795
  );
@@ -819,7 +799,7 @@ export function TodoList({
819
799
  // src/web/templates/auth-route.ts
820
800
  var auth_route_default = {
821
801
  filename: "apps/web/app/api/auth/[...all]/route.ts",
822
- template: `import { auth } from "@repo/auth";
802
+ template: `import { auth } from "@<%= projectName %>/auth";
823
803
  import { toNextJsHandler } from "better-auth/next-js";
824
804
 
825
805
  export const { GET, POST } = toNextJsHandler(auth);`
@@ -833,6 +813,32 @@ var auth_client_default = {
833
813
  export const authClient: ReturnType<typeof createAuthClient> = createAuthClient();`
834
814
  };
835
815
 
816
+ // src/web/templates/manifest.ts
817
+ var manifest_default = {
818
+ filename: "apps/web/app/manifest.json",
819
+ template: `{
820
+ "name": "<%= projectName %>",
821
+ "short_name": "<%= projectName %>",
822
+ "icons": [
823
+ {
824
+ "src": "/web-app-manifest-192x192.png",
825
+ "sizes": "192x192",
826
+ "type": "image/png",
827
+ "purpose": "maskable"
828
+ },
829
+ {
830
+ "src": "/web-app-manifest-512x512.png",
831
+ "sizes": "512x512",
832
+ "type": "image/png",
833
+ "purpose": "maskable"
834
+ }
835
+ ],
836
+ "theme_color": "#ffffff",
837
+ "background_color": "#ffffff",
838
+ "display": "standalone"
839
+ }`
840
+ };
841
+
836
842
  // src/web/index.ts
837
843
  var web = {
838
844
  templates: [
@@ -843,19 +849,24 @@ var web = {
843
849
  next_config_default,
844
850
  postcss_config_default,
845
851
  tsconfig_default,
846
- globals_css_default,
847
852
  layout_default,
848
853
  page_default,
849
854
  providers_default,
850
855
  auth_form_default,
851
856
  todo_list_default,
852
857
  auth_route_default,
853
- auth_client_default
858
+ auth_client_default,
859
+ manifest_default
854
860
  ],
855
861
  staticFiles: [
856
862
  { src: "web/static/fonts/GeistVF.woff", filename: "apps/web/app/fonts/GeistVF.woff" },
857
863
  { src: "web/static/fonts/GeistMonoVF.woff", filename: "apps/web/app/fonts/GeistMonoVF.woff" },
858
864
  { src: "web/static/favicon.ico", filename: "apps/web/app/favicon.ico" },
865
+ { src: "web/static/icon0.svg", filename: "apps/web/app/icon0.svg" },
866
+ { src: "web/static/icon1.png", filename: "apps/web/app/icon1.png" },
867
+ { src: "web/static/apple-icon.png", filename: "apps/web/app/apple-icon.png" },
868
+ { src: "web/static/public/web-app-manifest-192x192.png", filename: "apps/web/public/web-app-manifest-192x192.png" },
869
+ { src: "web/static/public/web-app-manifest-512x512.png", filename: "apps/web/public/web-app-manifest-512x512.png" },
859
870
  { src: "web/static/public/file-text.svg", filename: "apps/web/public/file-text.svg" },
860
871
  { src: "web/static/public/globe.svg", filename: "apps/web/public/globe.svg" },
861
872
  { src: "web/static/public/next.svg", filename: "apps/web/public/next.svg" },
@@ -895,7 +906,7 @@ var package_json_default3 = {
895
906
  "@nestjs/common": "^11.0.1",
896
907
  "@nestjs/core": "^11.0.1",
897
908
  "@nestjs/platform-express": "^11.0.1",
898
- "@repo/auth": "workspace:*",
909
+ "@<%= projectName %>/auth": "workspace:*",
899
910
  "@thallesp/nestjs-better-auth": "^2.5.1",
900
911
  "dotenv": "^17.3.1",
901
912
  "reflect-metadata": "^0.2.2",
@@ -921,7 +932,7 @@ var package_json_default3 = {
921
932
  "ts-loader": "^9.5.2",
922
933
  "ts-node": "^10.9.2",
923
934
  "tsconfig-paths": "^4.2.0",
924
- "typescript": "^5.7.3",
935
+ "typescript": "6.0.2",
925
936
  "typescript-eslint": "^8.20.0"
926
937
  },
927
938
  "jest": {
@@ -943,7 +954,7 @@ var eslint_config_default2 = {
943
954
  filename: "apps/api/eslint.config.mjs",
944
955
  template: `// @ts-check
945
956
  import eslint from '@eslint/js';
946
- import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
957
+ import prettierConfig from 'eslint-config-prettier';
947
958
  import globals from 'globals';
948
959
  import tseslint from 'typescript-eslint';
949
960
 
@@ -953,7 +964,7 @@ export default tseslint.config(
953
964
  },
954
965
  eslint.configs.recommended,
955
966
  ...tseslint.configs.recommendedTypeChecked,
956
- eslintPluginPrettierRecommended,
967
+ prettierConfig,
957
968
  {
958
969
  languageOptions: {
959
970
  globals: {
@@ -972,7 +983,6 @@ export default tseslint.config(
972
983
  '@typescript-eslint/no-explicit-any': 'off',
973
984
  '@typescript-eslint/no-floating-promises': 'warn',
974
985
  '@typescript-eslint/no-unsafe-argument': 'warn',
975
- "prettier/prettier": ["error", { endOfLine: "auto" }],
976
986
  },
977
987
  },
978
988
  );`
@@ -1016,7 +1026,8 @@ var tsconfig_default2 = {
1016
1026
  "forceConsistentCasingInFileNames": true,
1017
1027
  "noImplicitAny": false,
1018
1028
  "strictBindCallApply": false,
1019
- "noFallthroughCasesInSwitch": false
1029
+ "noFallthroughCasesInSwitch": false,
1030
+ "types": ["jest", "node"]
1020
1031
  }
1021
1032
  }`
1022
1033
  };
@@ -1083,7 +1094,7 @@ var app_module_default = {
1083
1094
  template: `import { Module } from '@nestjs/common';
1084
1095
  import { APP_GUARD } from '@nestjs/core';
1085
1096
  import { AuthGuard, AuthModule } from '@thallesp/nestjs-better-auth';
1086
- import { auth } from '@repo/auth';
1097
+ import { auth } from '@<%= projectName %>/auth';
1087
1098
  import { AppController } from './app.controller';
1088
1099
  import { TodosModule } from './todos/todos.module';
1089
1100
 
@@ -1108,7 +1119,7 @@ async function bootstrap() {
1108
1119
  app.enableCors({ origin: 'http://localhost:3000', credentials: true });
1109
1120
  await app.listen(process.env.PORT ?? 3001);
1110
1121
  }
1111
- bootstrap();`
1122
+ void bootstrap();`
1112
1123
  };
1113
1124
 
1114
1125
  // src/api/templates/todos-controller.ts
@@ -1293,7 +1304,7 @@ var api_default = api;
1293
1304
  var package_json_default4 = {
1294
1305
  filename: "packages/auth/package.json",
1295
1306
  template: `{
1296
- "name": "@repo/auth",
1307
+ "name": "@<%= projectName %>/auth",
1297
1308
  "version": "0.0.0",
1298
1309
  "private": true,
1299
1310
  "exports": {
@@ -1308,11 +1319,11 @@ var package_json_default4 = {
1308
1319
  "pg": "^8.14.1"
1309
1320
  },
1310
1321
  "devDependencies": {
1311
- "@repo/typescript-config": "workspace:*",
1322
+ "@<%= projectName %>/typescript-config": "workspace:*",
1312
1323
  "@types/pg": "^8.11.13",
1313
1324
  "auth": "^1.5.5",
1314
1325
  "dotenv-cli": "^11.0.0",
1315
- "typescript": "5.9.2"
1326
+ "typescript": "6.0.2"
1316
1327
  }
1317
1328
  }`
1318
1329
  };
@@ -1338,7 +1349,7 @@ export type Auth = typeof auth;`
1338
1349
  var tsconfig_default3 = {
1339
1350
  filename: "packages/auth/tsconfig.json",
1340
1351
  template: `{
1341
- "extends": "@repo/typescript-config/base.json",
1352
+ "extends": "@<%= projectName %>/typescript-config/base.json",
1342
1353
  "compilerOptions": {
1343
1354
  "outDir": "dist",
1344
1355
  "strictNullChecks": true
@@ -1358,10 +1369,13 @@ var auth_default = auth;
1358
1369
  var package_json_default5 = {
1359
1370
  filename: "packages/ui/package.json",
1360
1371
  template: `{
1361
- "name": "@repo/ui",
1372
+ "name": "@<%= projectName %>/ui",
1362
1373
  "version": "0.0.0",
1363
1374
  "private": true,
1364
1375
  "exports": {
1376
+ "./globals.css": "./src/globals.css",
1377
+ "./postcss.config": "./postcss.config.mjs",
1378
+ "./utils": "./src/utils.ts",
1365
1379
  "./*": "./src/*.tsx"
1366
1380
  },
1367
1381
  "scripts": {
@@ -1369,17 +1383,22 @@ var package_json_default5 = {
1369
1383
  "check-types": "tsc --noEmit"
1370
1384
  },
1371
1385
  "devDependencies": {
1372
- "@repo/eslint-config": "workspace:*",
1373
- "@repo/typescript-config": "workspace:*",
1386
+ "@<%= projectName %>/eslint-config": "workspace:*",
1387
+ "@<%= projectName %>/typescript-config": "workspace:*",
1388
+ "@tailwindcss/postcss": "^4.0.0",
1389
+ "tailwindcss": "^4.0.0",
1374
1390
  "@types/node": "^22.15.3",
1375
- "@types/react": "19.2.2",
1376
- "@types/react-dom": "19.2.2",
1391
+ "@types/react": "19.2.14",
1392
+ "@types/react-dom": "19.2.3",
1377
1393
  "eslint": "^9.39.1",
1378
- "typescript": "5.9.2"
1394
+ "typescript": "6.0.2"
1379
1395
  },
1380
1396
  "dependencies": {
1381
- "react": "^19.2.0",
1382
- "react-dom": "^19.2.0"
1397
+ "clsx": "^2.1.1",
1398
+ "next": "^16.2.1",
1399
+ "react": "^19.2.4",
1400
+ "react-dom": "^19.2.4",
1401
+ "tailwind-merge": "^3.3.0"
1383
1402
  }
1384
1403
  }`
1385
1404
  };
@@ -1390,18 +1409,30 @@ var button_default = {
1390
1409
  template: `"use client";
1391
1410
 
1392
1411
  import { ReactNode } from "react";
1412
+ import { cn } from "./utils";
1393
1413
 
1394
1414
  interface ButtonProps {
1395
1415
  children: ReactNode;
1416
+ onClick?: () => void;
1417
+ type?: "button" | "submit" | "reset";
1418
+ disabled?: boolean;
1396
1419
  className?: string;
1397
- appName: string;
1398
1420
  }
1399
1421
 
1400
- export const Button = ({ children, className, appName }: ButtonProps) => {
1422
+ export const Button = ({ children, onClick, type = "button", disabled, className }: ButtonProps) => {
1401
1423
  return (
1402
1424
  <button
1403
- className={className}
1404
- onClick={() => alert(\`Hello from your \${appName} app!\`)}
1425
+ type={type}
1426
+ onClick={onClick}
1427
+ disabled={disabled}
1428
+ className={cn(
1429
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all",
1430
+ "h-9 px-4 py-2",
1431
+ "bg-white text-gray-900 shadow-xs hover:bg-gray-100",
1432
+ "disabled:pointer-events-none disabled:opacity-50",
1433
+ "outline-none focus-visible:ring-2 focus-visible:ring-white/50",
1434
+ className
1435
+ )}
1405
1436
  >
1406
1437
  {children}
1407
1438
  </button>
@@ -1460,29 +1491,124 @@ export function Code({
1460
1491
  // src/ui/templates/link.ts
1461
1492
  var link_default = {
1462
1493
  filename: "packages/ui/src/link.tsx",
1463
- template: `"use client";
1464
-
1465
- import { AnchorHTMLAttributes } from "react";
1494
+ template: `import NextLink, { type LinkProps } from "next/link";
1495
+ import { type PropsWithChildren } from "react";
1496
+ import { cn } from "./utils";
1466
1497
 
1467
- export function Link({ children, ...props }: AnchorHTMLAttributes<HTMLAnchorElement>) {
1498
+ export function Link({
1499
+ href,
1500
+ children,
1501
+ className,
1502
+ ...rest
1503
+ }: PropsWithChildren<LinkProps & { className?: string }>) {
1468
1504
  return (
1469
- <a
1470
- target="_blank"
1471
- rel="noopener noreferrer"
1472
- className="hover:underline underline-offset-2 hover:text-gray-900 transition-colors"
1473
- {...props}
1505
+ <NextLink
1506
+ href={href}
1507
+ {...rest}
1508
+ className={cn(
1509
+ "underline decoration-muted-foreground hover:decoration-foreground transition-colors",
1510
+ className
1511
+ )}
1474
1512
  >
1475
1513
  {children}
1476
- </a>
1514
+ </NextLink>
1477
1515
  );
1478
1516
  }`
1479
1517
  };
1480
1518
 
1519
+ // src/ui/templates/logo.ts
1520
+ var logo_default = {
1521
+ filename: "packages/ui/src/logo.tsx",
1522
+ template: `import { cn } from "./utils";
1523
+
1524
+ interface LogoProps {
1525
+ className?: string;
1526
+ }
1527
+
1528
+ export function Logo({ className }: LogoProps) {
1529
+ return (
1530
+ <svg
1531
+ width="196"
1532
+ height="138"
1533
+ viewBox="0 0 196 138"
1534
+ fill="none"
1535
+ xmlns="http://www.w3.org/2000/svg"
1536
+ className={cn("text-foreground", className)}
1537
+ >
1538
+ <path
1539
+ d="M98 35C102.665 35 107.243 35.2232 111.707 35.6514C111.243 38.1972 111 40.8202 111 43.5C111 67.5244 130.476 87 154.5 87C165.156 87 174.914 83.1658 182.478 76.8057C183.476 79.9455 184 83.186 184 86.5C184 114.943 145.496 138 98 138C50.5035 138 12 114.943 12 86.5C12 83.1861 12.5228 79.9454 13.5215 76.8057C21.0851 83.1661 30.8441 87 41.5 87C65.5244 87 85 67.5244 85 43.5C85 40.8202 84.7559 38.1973 84.292 35.6514C88.7559 35.2232 93.3345 35 98 35ZM38.5 0C59.763 0 77 17.237 77 38.5C77 59.763 59.763 77 38.5 77C17.237 77 0 59.763 0 38.5C0 17.237 17.237 0 38.5 0ZM157.5 0C178.763 0 196 17.237 196 38.5C196 59.763 178.763 77 157.5 77C136.237 77 119 59.763 119 38.5C119 17.237 136.237 0 157.5 0Z"
1540
+ fill="currentColor"
1541
+ />
1542
+ </svg>
1543
+ );
1544
+ }`
1545
+ };
1546
+
1547
+ // src/ui/templates/utils.ts
1548
+ var utils_default = {
1549
+ filename: "packages/ui/src/utils.ts",
1550
+ template: `import { clsx, type ClassValue } from "clsx";
1551
+ import { twMerge } from "tailwind-merge";
1552
+
1553
+ export function cn(...inputs: ClassValue[]) {
1554
+ return twMerge(clsx(inputs));
1555
+ }`
1556
+ };
1557
+
1558
+ // src/ui/templates/globals-css.ts
1559
+ var globals_css_default = {
1560
+ filename: "packages/ui/src/globals.css",
1561
+ template: `@import 'tailwindcss';
1562
+ @source "../../../apps/**/*.{ts,tsx}";
1563
+ @source "../**/*.{ts,tsx}";
1564
+
1565
+ :root {
1566
+ --background: oklch(0.145 0 0);
1567
+ --foreground: oklch(0.985 0 0);
1568
+ --muted-foreground: oklch(0.708 0 0);
1569
+ --border: oklch(0.469 0 0);
1570
+ }
1571
+
1572
+ @theme inline {
1573
+ --color-background: var(--background);
1574
+ --color-foreground: var(--foreground);
1575
+ --color-muted-foreground: var(--muted-foreground);
1576
+ --color-border: var(--border);
1577
+ }
1578
+
1579
+ @layer base {
1580
+ html,
1581
+ body {
1582
+ height: 100%;
1583
+ }
1584
+ body {
1585
+ background-color: var(--background);
1586
+ color: var(--foreground);
1587
+ -webkit-font-smoothing: antialiased;
1588
+ }
1589
+ * {
1590
+ border-color: var(--border);
1591
+ }
1592
+ }`
1593
+ };
1594
+
1595
+ // src/ui/templates/postcss-config.ts
1596
+ var postcss_config_default2 = {
1597
+ filename: "packages/ui/postcss.config.mjs",
1598
+ template: `const config = {
1599
+ plugins: {
1600
+ "@tailwindcss/postcss": {},
1601
+ },
1602
+ };
1603
+
1604
+ export default config;`
1605
+ };
1606
+
1481
1607
  // src/ui/templates/tsconfig.ts
1482
1608
  var tsconfig_default4 = {
1483
1609
  filename: "packages/ui/tsconfig.json",
1484
1610
  template: `{
1485
- "extends": "@repo/typescript-config/react-library.json",
1611
+ "extends": "@<%= projectName %>/typescript-config/react-library.json",
1486
1612
  "compilerOptions": {
1487
1613
  "outDir": "dist",
1488
1614
  "strictNullChecks": true
@@ -1495,7 +1621,7 @@ var tsconfig_default4 = {
1495
1621
  // src/ui/templates/eslint-config.ts
1496
1622
  var eslint_config_default3 = {
1497
1623
  filename: "packages/ui/eslint.config.mjs",
1498
- template: `import { config } from "@repo/eslint-config/react-internal";
1624
+ template: `import { config } from "@<%= projectName %>/eslint-config/react-internal";
1499
1625
 
1500
1626
  /** @type {import("eslint").Linter.Config} */
1501
1627
  export default config;`
@@ -1503,7 +1629,7 @@ export default config;`
1503
1629
 
1504
1630
  // src/ui/index.ts
1505
1631
  var ui = {
1506
- templates: [package_json_default5, button_default, card_default, code_default, link_default, tsconfig_default4, eslint_config_default3]
1632
+ templates: [package_json_default5, button_default, card_default, code_default, link_default, logo_default, utils_default, globals_css_default, postcss_config_default2, tsconfig_default4, eslint_config_default3]
1507
1633
  };
1508
1634
  var ui_default = ui;
1509
1635
 
@@ -1511,7 +1637,7 @@ var ui_default = ui;
1511
1637
  var package_json_default6 = {
1512
1638
  filename: "packages/eslint-config/package.json",
1513
1639
  template: `{
1514
- "name": "@repo/eslint-config",
1640
+ "name": "@<%= projectName %>/eslint-config",
1515
1641
  "version": "0.0.0",
1516
1642
  "type": "module",
1517
1643
  "private": true,
@@ -1689,7 +1815,7 @@ var eslint_config_default4 = eslintConfig;
1689
1815
  var package_json_default7 = {
1690
1816
  filename: "packages/typescript-config/package.json",
1691
1817
  template: `{
1692
- "name": "@repo/typescript-config",
1818
+ "name": "@<%= projectName %>/typescript-config",
1693
1819
  "version": "0.0.0",
1694
1820
  "private": true,
1695
1821
  "license": "MIT",
Binary file
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000"><g clip-path="url(#SvgjsClipPath1144)"><rect width="1000" height="1000" fill="#000000"></rect><g transform="matrix(4.081632653061225,0,0,4.081632653061225,100,218.36734693877548)"><svg xmlns="http://www.w3.org/2000/svg" width="196" height="138" viewBox="0 0 196 138" fill="none"><path d="M98 35C102.665 35 107.243 35.2232 111.707 35.6514C111.243 38.1972 111 40.8202 111 43.5C111 67.5244 130.476 87 154.5 87C165.156 87 174.914 83.1658 182.478 76.8057C183.476 79.9455 184 83.186 184 86.5C184 114.943 145.496 138 98 138C50.5035 138 12 114.943 12 86.5C12 83.1861 12.5228 79.9454 13.5215 76.8057C21.0851 83.1661 30.8441 87 41.5 87C65.5244 87 85 67.5244 85 43.5C85 40.8202 84.7559 38.1973 84.292 35.6514C88.7559 35.2232 93.3345 35 98 35ZM38.5 0C59.763 0 77 17.237 77 38.5C77 59.763 59.763 77 38.5 77C17.237 77 0 59.763 0 38.5C0 17.237 17.237 0 38.5 0ZM157.5 0C178.763 0 196 17.237 196 38.5C196 59.763 178.763 77 157.5 77C136.237 77 119 59.763 119 38.5C119 17.237 136.237 0 157.5 0Z" fill="white"></path></svg></g></g><defs><clipPath id="SvgjsClipPath1144"><rect width="1000" height="1000" x="0" y="0" rx="350" ry="350"></rect></clipPath></defs></svg>
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newt-app/templates",
3
- "version": "0.0.2",
3
+ "version": "0.1.0",
4
4
  "private": false,
5
5
  "description": "Templates for newt-app",
6
6
  "type": "module",
@@ -18,6 +18,7 @@
18
18
  },
19
19
  "scripts": {
20
20
  "build": "tsup",
21
+ "build:watch": "tsup --watch",
21
22
  "dev": "tsup --watch"
22
23
  }
23
24
  }