create-velox-app 0.4.2 → 0.4.4
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/cli.js +0 -0
- package/dist/index.js +21 -14
- package/dist/index.js.map +1 -1
- package/dist/templates/auth.d.ts +6 -3
- package/dist/templates/auth.d.ts.map +1 -1
- package/dist/templates/auth.js +56 -1110
- package/dist/templates/auth.js.map +1 -1
- package/dist/templates/compiler.d.ts +68 -0
- package/dist/templates/compiler.d.ts.map +1 -0
- package/dist/templates/compiler.js +149 -0
- package/dist/templates/compiler.js.map +1 -0
- package/dist/templates/default.d.ts +5 -2
- package/dist/templates/default.d.ts.map +1 -1
- package/dist/templates/default.js +51 -508
- package/dist/templates/default.js.map +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +19 -10
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/placeholders.d.ts +70 -0
- package/dist/templates/placeholders.d.ts.map +1 -0
- package/dist/templates/placeholders.js +145 -0
- package/dist/templates/placeholders.js.map +1 -0
- package/dist/templates/shared/index.d.ts +9 -0
- package/dist/templates/shared/index.d.ts.map +1 -0
- package/dist/templates/shared/index.js +9 -0
- package/dist/templates/shared/index.js.map +1 -0
- package/dist/templates/shared/root.d.ts +14 -0
- package/dist/templates/shared/root.d.ts.map +1 -0
- package/dist/templates/shared/root.js +43 -0
- package/dist/templates/shared/root.js.map +1 -0
- package/dist/templates/shared/web-base.d.ts +18 -0
- package/dist/templates/shared/web-base.d.ts.map +1 -0
- package/dist/templates/shared/web-base.js +63 -0
- package/dist/templates/shared/web-base.js.map +1 -0
- package/dist/templates/shared/web-styles.d.ts +10 -0
- package/dist/templates/shared/web-styles.d.ts.map +1 -0
- package/dist/templates/shared/web-styles.js +26 -0
- package/dist/templates/shared/web-styles.js.map +1 -0
- package/dist/templates/shared.d.ts +3 -14
- package/dist/templates/shared.d.ts.map +1 -1
- package/dist/templates/shared.js +7 -290
- package/dist/templates/shared.js.map +1 -1
- package/dist/templates/source/api/config/app.d.ts +13 -0
- package/dist/templates/source/api/config/app.d.ts.map +1 -0
- package/dist/templates/source/api/config/app.js +14 -0
- package/dist/templates/source/api/config/app.js.map +1 -0
- package/dist/templates/source/api/config/auth.d.ts +34 -0
- package/dist/templates/source/api/config/auth.d.ts.map +1 -0
- package/dist/templates/source/api/config/auth.js +165 -0
- package/dist/templates/source/api/config/auth.js.map +1 -0
- package/dist/templates/source/api/config/index.auth.d.ts +6 -0
- package/dist/templates/source/api/config/index.auth.d.ts.map +1 -0
- package/dist/templates/source/api/config/index.auth.js +6 -0
- package/dist/templates/source/api/config/index.auth.js.map +1 -0
- package/dist/templates/source/api/config/index.default.d.ts +5 -0
- package/dist/templates/source/api/config/index.default.d.ts.map +1 -0
- package/dist/templates/source/api/config/index.default.js +5 -0
- package/dist/templates/source/api/config/index.default.js.map +1 -0
- package/dist/templates/source/api/database/index.d.ts +9 -0
- package/dist/templates/source/api/database/index.d.ts.map +1 -0
- package/dist/templates/source/api/database/index.js +18 -0
- package/dist/templates/source/api/database/index.js.map +1 -0
- package/dist/templates/source/api/index.auth.d.ts +5 -0
- package/dist/templates/source/api/index.auth.d.ts.map +1 -0
- package/dist/templates/source/api/index.auth.js +59 -0
- package/dist/templates/source/api/index.auth.js.map +1 -0
- package/dist/templates/source/api/index.default.d.ts +5 -0
- package/dist/templates/source/api/index.default.d.ts.map +1 -0
- package/dist/templates/source/api/index.default.js +56 -0
- package/dist/templates/source/api/index.default.js.map +1 -0
- package/dist/templates/source/api/prisma.config.d.ts +9 -0
- package/dist/templates/source/api/prisma.config.d.ts.map +1 -0
- package/dist/templates/source/api/prisma.config.js +15 -0
- package/dist/templates/source/api/prisma.config.js.map +1 -0
- package/dist/templates/source/api/procedures/auth.d.ts +14 -0
- package/dist/templates/source/api/procedures/auth.d.ts.map +1 -0
- package/dist/templates/source/api/procedures/auth.js +221 -0
- package/dist/templates/source/api/procedures/auth.js.map +1 -0
- package/dist/templates/source/api/procedures/health.d.ts +5 -0
- package/dist/templates/source/api/procedures/health.d.ts.map +1 -0
- package/dist/templates/source/api/procedures/health.js +21 -0
- package/dist/templates/source/api/procedures/health.js.map +1 -0
- package/dist/templates/source/api/procedures/index.auth.d.ts +7 -0
- package/dist/templates/source/api/procedures/index.auth.d.ts.map +1 -0
- package/dist/templates/source/api/procedures/index.auth.js +7 -0
- package/dist/templates/source/api/procedures/index.auth.js.map +1 -0
- package/dist/templates/source/api/procedures/index.default.d.ts +6 -0
- package/dist/templates/source/api/procedures/index.default.d.ts.map +1 -0
- package/dist/templates/source/api/procedures/index.default.js +6 -0
- package/dist/templates/source/api/procedures/index.default.js.map +1 -0
- package/dist/templates/source/api/procedures/users.auth.d.ts +7 -0
- package/dist/templates/source/api/procedures/users.auth.d.ts.map +1 -0
- package/dist/templates/source/api/procedures/users.auth.js +111 -0
- package/dist/templates/source/api/procedures/users.auth.js.map +1 -0
- package/dist/templates/source/api/procedures/users.default.d.ts +5 -0
- package/dist/templates/source/api/procedures/users.default.d.ts.map +1 -0
- package/dist/templates/source/api/procedures/users.default.js +86 -0
- package/dist/templates/source/api/procedures/users.default.js.map +1 -0
- package/dist/templates/source/api/schemas/index.d.ts +5 -0
- package/dist/templates/source/api/schemas/index.d.ts.map +1 -0
- package/dist/templates/source/api/schemas/index.js +5 -0
- package/dist/templates/source/api/schemas/index.js.map +1 -0
- package/dist/templates/source/api/schemas/user.d.ts +11 -0
- package/dist/templates/source/api/schemas/user.d.ts.map +1 -0
- package/dist/templates/source/api/schemas/user.js +20 -0
- package/dist/templates/source/api/schemas/user.js.map +1 -0
- package/dist/templates/source/api/tsup.config.d.ts +3 -0
- package/dist/templates/source/api/tsup.config.d.ts.map +1 -0
- package/dist/templates/source/api/tsup.config.js +10 -0
- package/dist/templates/source/api/tsup.config.js.map +1 -0
- package/dist/templates/source/web/main.d.ts +9 -0
- package/dist/templates/source/web/main.d.ts.map +1 -0
- package/dist/templates/source/web/main.js +27 -0
- package/dist/templates/source/web/main.js.map +1 -0
- package/dist/templates/source/web/routes/__root.d.ts +2 -0
- package/dist/templates/source/web/routes/__root.d.ts.map +1 -0
- package/dist/templates/source/web/routes/__root.js +28 -0
- package/dist/templates/source/web/routes/__root.js.map +1 -0
- package/dist/templates/source/web/routes/about.d.ts +2 -0
- package/dist/templates/source/web/routes/about.d.ts.map +1 -0
- package/dist/templates/source/web/routes/about.js +33 -0
- package/dist/templates/source/web/routes/about.js.map +1 -0
- package/dist/templates/source/web/routes/index.auth.d.ts +2 -0
- package/dist/templates/source/web/routes/index.auth.d.ts.map +1 -0
- package/dist/templates/source/web/routes/index.auth.js +159 -0
- package/dist/templates/source/web/routes/index.auth.js.map +1 -0
- package/dist/templates/source/web/routes/index.default.d.ts +2 -0
- package/dist/templates/source/web/routes/index.default.d.ts.map +1 -0
- package/dist/templates/source/web/routes/index.default.js +60 -0
- package/dist/templates/source/web/routes/index.default.js.map +1 -0
- package/dist/templates/source/web/vite.config.d.ts +3 -0
- package/dist/templates/source/web/vite.config.d.ts.map +1 -0
- package/dist/templates/source/web/vite.config.js +22 -0
- package/dist/templates/source/web/vite.config.js.map +1 -0
- package/package.json +11 -9
- package/src/templates/source/api/config/app.ts +13 -0
- package/src/templates/source/api/config/auth.ts +202 -0
- package/src/templates/source/api/config/database.ts +22 -0
- package/src/templates/source/api/env.auth +22 -0
- package/src/templates/source/api/env.default +13 -0
- package/src/templates/source/api/index.auth.ts +30 -0
- package/src/templates/source/api/index.default.ts +27 -0
- package/src/templates/source/api/package.auth.json +40 -0
- package/src/templates/source/api/package.default.json +38 -0
- package/src/templates/source/api/prisma/schema.auth.prisma +30 -0
- package/src/templates/source/api/prisma/schema.default.prisma +28 -0
- package/src/templates/source/api/prisma.config.ts +15 -0
- package/src/templates/source/api/procedures/auth.ts +285 -0
- package/src/templates/source/api/procedures/health.ts +24 -0
- package/src/templates/source/api/procedures/users.auth.ts +170 -0
- package/src/templates/source/api/procedures/users.default.ts +119 -0
- package/src/templates/source/api/schemas/user.ts +29 -0
- package/src/templates/source/api/tsconfig.json +12 -0
- package/src/templates/source/api/tsup.config.ts +10 -0
- package/src/templates/source/root/CLAUDE.auth.md +148 -0
- package/src/templates/source/root/CLAUDE.default.md +128 -0
- package/src/templates/source/root/README.md +72 -0
- package/src/templates/source/root/gitignore +37 -0
- package/src/templates/source/root/package.json +17 -0
- package/src/templates/source/root/pnpm-workspace.yaml +2 -0
- package/src/templates/source/root/tsconfig.json +19 -0
- package/src/templates/source/web/App.module.css +282 -0
- package/src/templates/source/web/favicon.svg +12 -0
- package/src/templates/source/web/index.html +13 -0
- package/src/templates/source/web/main.tsx +38 -0
- package/src/templates/source/web/package.json +26 -0
- package/src/templates/source/web/routes/__root.tsx +31 -0
- package/src/templates/source/web/routes/about.tsx +36 -0
- package/src/templates/source/web/routes/index.auth.tsx +230 -0
- package/src/templates/source/web/routes/index.default.tsx +79 -0
- package/src/templates/source/web/styles/global.css +90 -0
- package/src/templates/source/web/tsconfig.json +24 -0
- package/src/templates/source/web/vite.config.ts +22 -0
- package/LICENSE +0 -21
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code and other AI assistants.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
**__PROJECT_NAME__** is a VeloxTS full-stack application with:
|
|
8
|
+
- **Backend**: Fastify + VeloxTS (apps/api)
|
|
9
|
+
- **Frontend**: React + Vite + TanStack Router (apps/web)
|
|
10
|
+
- **Database**: Prisma with SQLite
|
|
11
|
+
- **Auth**: JWT authentication with guards
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
__RUN_CMD__ dev # Start both API (__API_PORT__) and Web (__WEB_PORT__)
|
|
17
|
+
__RUN_CMD__ build # Build both apps
|
|
18
|
+
__RUN_CMD__ db:push # Push database schema
|
|
19
|
+
__RUN_CMD__ db:studio # Open Prisma Studio
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
### Workspace Structure
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
apps/
|
|
28
|
+
├── api/ # Backend (VeloxTS + Fastify)
|
|
29
|
+
│ ├── src/
|
|
30
|
+
│ │ ├── procedures/ # API procedures
|
|
31
|
+
│ │ ├── schemas/ # Zod schemas
|
|
32
|
+
│ │ └── config/ # App configuration
|
|
33
|
+
│ └── prisma/
|
|
34
|
+
│ └── schema.prisma
|
|
35
|
+
│
|
|
36
|
+
└── web/ # Frontend (React + Vite)
|
|
37
|
+
└── src/
|
|
38
|
+
├── routes/ # TanStack Router pages
|
|
39
|
+
├── components/ # React components
|
|
40
|
+
└── styles/ # CSS modules
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### API Development (apps/api)
|
|
44
|
+
|
|
45
|
+
**Creating a new procedure:**
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// apps/api/src/procedures/posts.ts
|
|
49
|
+
import { defineProcedures, procedure, z } from '@veloxts/velox';
|
|
50
|
+
|
|
51
|
+
export const postProcedures = defineProcedures('posts', {
|
|
52
|
+
// GET /api/posts/:id
|
|
53
|
+
getPost: procedure()
|
|
54
|
+
.input(z.object({ id: z.string().uuid() }))
|
|
55
|
+
.output(PostSchema)
|
|
56
|
+
.query(async ({ input, ctx }) => {
|
|
57
|
+
return ctx.db.post.findUnique({ where: { id: input.id } });
|
|
58
|
+
}),
|
|
59
|
+
|
|
60
|
+
// POST /api/posts
|
|
61
|
+
createPost: procedure()
|
|
62
|
+
.input(CreatePostSchema)
|
|
63
|
+
.output(PostSchema)
|
|
64
|
+
.mutation(async ({ input, ctx }) => {
|
|
65
|
+
return ctx.db.post.create({ data: input });
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Then register in `src/procedures/index.ts` and add to collections in `src/index.ts`.
|
|
71
|
+
|
|
72
|
+
### Frontend Development (apps/web)
|
|
73
|
+
|
|
74
|
+
**Creating a new route:**
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// apps/web/src/routes/posts.tsx
|
|
78
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
79
|
+
import { useQuery } from '@veloxts/client';
|
|
80
|
+
|
|
81
|
+
export const Route = createFileRoute('/posts')({
|
|
82
|
+
component: PostsPage,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
function PostsPage() {
|
|
86
|
+
const { data: posts, isLoading } = useQuery(['posts'], '/posts');
|
|
87
|
+
|
|
88
|
+
if (isLoading) return <p>Loading...</p>;
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<ul>
|
|
92
|
+
{posts?.data.map(post => (
|
|
93
|
+
<li key={post.id}>{post.title}</li>
|
|
94
|
+
))}
|
|
95
|
+
</ul>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Type Safety
|
|
101
|
+
|
|
102
|
+
VeloxTS provides end-to-end type safety without code generation:
|
|
103
|
+
|
|
104
|
+
1. **Define schemas** in `apps/api/src/schemas/`
|
|
105
|
+
2. **Use in procedures** with `.input()` and `.output()`
|
|
106
|
+
3. **Import in frontend** via `@veloxts/client` hooks
|
|
107
|
+
4. Types flow automatically from backend to frontend
|
|
108
|
+
|
|
109
|
+
## Authentication
|
|
110
|
+
|
|
111
|
+
This project includes full JWT authentication:
|
|
112
|
+
|
|
113
|
+
| Endpoint | Method | Description |
|
|
114
|
+
|----------|--------|-------------|
|
|
115
|
+
| `/api/auth/register` | POST | Create new account |
|
|
116
|
+
| `/api/auth/login` | POST | Login and get tokens |
|
|
117
|
+
| `/api/auth/refresh` | POST | Refresh access token |
|
|
118
|
+
| `/api/auth/logout` | POST | Revoke current token |
|
|
119
|
+
| `/api/auth/me` | GET | Get current user (protected) |
|
|
120
|
+
|
|
121
|
+
### Environment Variables (Required for Production)
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
JWT_SECRET=<64+ chars> # Generate: openssl rand -base64 64
|
|
125
|
+
JWT_REFRESH_SECRET=<64+ chars> # Generate: openssl rand -base64 64
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Procedure Naming Conventions
|
|
129
|
+
|
|
130
|
+
| Procedure Name | HTTP Method | Route |
|
|
131
|
+
|----------------|-------------|-------|
|
|
132
|
+
| `getUser` | GET | `/users/:id` |
|
|
133
|
+
| `listUsers` | GET | `/users` |
|
|
134
|
+
| `createUser` | POST | `/users` |
|
|
135
|
+
| `updateUser` | PUT | `/users/:id` |
|
|
136
|
+
| `patchUser` | PATCH | `/users/:id` |
|
|
137
|
+
| `deleteUser` | DELETE | `/users/:id` |
|
|
138
|
+
|
|
139
|
+
## Database
|
|
140
|
+
|
|
141
|
+
After schema changes:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
__RUN_CMD__ db:push # Apply changes
|
|
145
|
+
__RUN_CMD__ db:generate # Regenerate client
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Access via context: `ctx.db.user.findMany()`
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code and other AI assistants.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
**__PROJECT_NAME__** is a VeloxTS full-stack application with:
|
|
8
|
+
- **Backend**: Fastify + VeloxTS (apps/api)
|
|
9
|
+
- **Frontend**: React + Vite + TanStack Router (apps/web)
|
|
10
|
+
- **Database**: Prisma with SQLite
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
__RUN_CMD__ dev # Start both API (__API_PORT__) and Web (__WEB_PORT__)
|
|
16
|
+
__RUN_CMD__ build # Build both apps
|
|
17
|
+
__RUN_CMD__ db:push # Push database schema
|
|
18
|
+
__RUN_CMD__ db:studio # Open Prisma Studio
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Architecture
|
|
22
|
+
|
|
23
|
+
### Workspace Structure
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
apps/
|
|
27
|
+
├── api/ # Backend (VeloxTS + Fastify)
|
|
28
|
+
│ ├── src/
|
|
29
|
+
│ │ ├── procedures/ # API procedures
|
|
30
|
+
│ │ ├── schemas/ # Zod schemas
|
|
31
|
+
│ │ └── config/ # App configuration
|
|
32
|
+
│ └── prisma/
|
|
33
|
+
│ └── schema.prisma
|
|
34
|
+
│
|
|
35
|
+
└── web/ # Frontend (React + Vite)
|
|
36
|
+
└── src/
|
|
37
|
+
├── routes/ # TanStack Router pages
|
|
38
|
+
├── components/ # React components
|
|
39
|
+
└── styles/ # CSS modules
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### API Development (apps/api)
|
|
43
|
+
|
|
44
|
+
**Creating a new procedure:**
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// apps/api/src/procedures/posts.ts
|
|
48
|
+
import { defineProcedures, procedure, z } from '@veloxts/velox';
|
|
49
|
+
|
|
50
|
+
export const postProcedures = defineProcedures('posts', {
|
|
51
|
+
// GET /api/posts/:id
|
|
52
|
+
getPost: procedure()
|
|
53
|
+
.input(z.object({ id: z.string().uuid() }))
|
|
54
|
+
.output(PostSchema)
|
|
55
|
+
.query(async ({ input, ctx }) => {
|
|
56
|
+
return ctx.db.post.findUnique({ where: { id: input.id } });
|
|
57
|
+
}),
|
|
58
|
+
|
|
59
|
+
// POST /api/posts
|
|
60
|
+
createPost: procedure()
|
|
61
|
+
.input(CreatePostSchema)
|
|
62
|
+
.output(PostSchema)
|
|
63
|
+
.mutation(async ({ input, ctx }) => {
|
|
64
|
+
return ctx.db.post.create({ data: input });
|
|
65
|
+
}),
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Then register in `src/procedures/index.ts` and add to collections in `src/index.ts`.
|
|
70
|
+
|
|
71
|
+
### Frontend Development (apps/web)
|
|
72
|
+
|
|
73
|
+
**Creating a new route:**
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// apps/web/src/routes/posts.tsx
|
|
77
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
78
|
+
import { useQuery } from '@veloxts/client';
|
|
79
|
+
|
|
80
|
+
export const Route = createFileRoute('/posts')({
|
|
81
|
+
component: PostsPage,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
function PostsPage() {
|
|
85
|
+
const { data: posts, isLoading } = useQuery(['posts'], '/posts');
|
|
86
|
+
|
|
87
|
+
if (isLoading) return <p>Loading...</p>;
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<ul>
|
|
91
|
+
{posts?.data.map(post => (
|
|
92
|
+
<li key={post.id}>{post.title}</li>
|
|
93
|
+
))}
|
|
94
|
+
</ul>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Type Safety
|
|
100
|
+
|
|
101
|
+
VeloxTS provides end-to-end type safety without code generation:
|
|
102
|
+
|
|
103
|
+
1. **Define schemas** in `apps/api/src/schemas/`
|
|
104
|
+
2. **Use in procedures** with `.input()` and `.output()`
|
|
105
|
+
3. **Import in frontend** via `@veloxts/client` hooks
|
|
106
|
+
4. Types flow automatically from backend to frontend
|
|
107
|
+
|
|
108
|
+
## Procedure Naming Conventions
|
|
109
|
+
|
|
110
|
+
| Procedure Name | HTTP Method | Route |
|
|
111
|
+
|----------------|-------------|-------|
|
|
112
|
+
| `getUser` | GET | `/users/:id` |
|
|
113
|
+
| `listUsers` | GET | `/users` |
|
|
114
|
+
| `createUser` | POST | `/users` |
|
|
115
|
+
| `updateUser` | PUT | `/users/:id` |
|
|
116
|
+
| `patchUser` | PATCH | `/users/:id` |
|
|
117
|
+
| `deleteUser` | DELETE | `/users/:id` |
|
|
118
|
+
|
|
119
|
+
## Database
|
|
120
|
+
|
|
121
|
+
After schema changes:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
__RUN_CMD__ db:push # Apply changes
|
|
125
|
+
__RUN_CMD__ db:generate # Regenerate client
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Access via context: `ctx.db.user.findMany()`
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# __PROJECT_NAME__
|
|
2
|
+
|
|
3
|
+
A VeloxTS full-stack application - TypeScript from backend to frontend.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
### Install Dependencies
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
__PACKAGE_MANAGER__ install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Setup Database
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
__RUN_CMD__ db:push
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Start Development
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
__RUN_CMD__ dev
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This starts both:
|
|
26
|
+
- **API** at http://localhost:__API_PORT__
|
|
27
|
+
- **Web** at http://localhost:__WEB_PORT__
|
|
28
|
+
|
|
29
|
+
## Project Structure
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
__PROJECT_NAME__/
|
|
33
|
+
├── apps/
|
|
34
|
+
│ ├── api/ # Backend API (Fastify + VeloxTS)
|
|
35
|
+
│ │ ├── src/
|
|
36
|
+
│ │ │ ├── procedures/ # API endpoints
|
|
37
|
+
│ │ │ ├── schemas/ # Zod validation
|
|
38
|
+
│ │ │ └── index.ts # Entry point
|
|
39
|
+
│ │ └── prisma/ # Database schema
|
|
40
|
+
│ │
|
|
41
|
+
│ └── web/ # React Frontend (Vite + TanStack)
|
|
42
|
+
│ └── src/
|
|
43
|
+
│ ├── routes/ # File-based routing
|
|
44
|
+
│ └── main.tsx # Entry point
|
|
45
|
+
│
|
|
46
|
+
├── package.json # Workspace root
|
|
47
|
+
└── pnpm-workspace.yaml # Workspace config
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Available Scripts
|
|
51
|
+
|
|
52
|
+
| Command | Description |
|
|
53
|
+
|---------|-------------|
|
|
54
|
+
| `__RUN_CMD__ dev` | Start both API and Web in development |
|
|
55
|
+
| `__RUN_CMD__ build` | Build both apps for production |
|
|
56
|
+
| `__RUN_CMD__ db:push` | Push database schema changes |
|
|
57
|
+
| `__RUN_CMD__ db:studio` | Open Prisma Studio |
|
|
58
|
+
|
|
59
|
+
## Type Safety
|
|
60
|
+
|
|
61
|
+
VeloxTS provides end-to-end type safety:
|
|
62
|
+
|
|
63
|
+
1. **Backend**: Define procedures with Zod schemas
|
|
64
|
+
2. **Frontend**: Import types directly, use type-safe hooks
|
|
65
|
+
3. **No code generation** - types flow automatically
|
|
66
|
+
|
|
67
|
+
## Learn More
|
|
68
|
+
|
|
69
|
+
- [VeloxTS Documentation](https://veloxts.dev)
|
|
70
|
+
- [React](https://react.dev/)
|
|
71
|
+
- [TanStack Router](https://tanstack.com/router)
|
|
72
|
+
- [Prisma](https://www.prisma.io/)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
|
|
4
|
+
# Build output
|
|
5
|
+
dist/
|
|
6
|
+
*.tsbuildinfo
|
|
7
|
+
|
|
8
|
+
# Environment variables
|
|
9
|
+
.env
|
|
10
|
+
.env.local
|
|
11
|
+
|
|
12
|
+
# Database
|
|
13
|
+
*.db
|
|
14
|
+
*.db-journal
|
|
15
|
+
|
|
16
|
+
# Generated Prisma client
|
|
17
|
+
**/generated/
|
|
18
|
+
|
|
19
|
+
# Logs
|
|
20
|
+
logs/
|
|
21
|
+
*.log
|
|
22
|
+
|
|
23
|
+
# OS
|
|
24
|
+
.DS_Store
|
|
25
|
+
Thumbs.db
|
|
26
|
+
|
|
27
|
+
# IDE
|
|
28
|
+
.vscode/
|
|
29
|
+
.idea/
|
|
30
|
+
*.swp
|
|
31
|
+
*.swo
|
|
32
|
+
|
|
33
|
+
# Turbo
|
|
34
|
+
.turbo/
|
|
35
|
+
|
|
36
|
+
# Vite
|
|
37
|
+
apps/web/.vite/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PROJECT_NAME__",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "__RUN_CMD__ --parallel -r dev",
|
|
8
|
+
"build": "__RUN_CMD__ -r build",
|
|
9
|
+
"type-check": "__RUN_CMD__ -r type-check",
|
|
10
|
+
"db:push": "__RUN_CMD__ -F api db:push",
|
|
11
|
+
"db:generate": "__RUN_CMD__ -F api db:generate",
|
|
12
|
+
"db:studio": "__RUN_CMD__ -F api db:studio"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"typescript": "5.9.3"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"module": "ES2022",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"lib": ["ES2022"],
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"allowSyntheticDefaultImports": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"isolatedModules": true,
|
|
15
|
+
"noUnusedLocals": true,
|
|
16
|
+
"noUnusedParameters": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/* App Styles */
|
|
2
|
+
|
|
3
|
+
.app {
|
|
4
|
+
min-height: 100vh;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* Navigation */
|
|
10
|
+
.nav {
|
|
11
|
+
display: flex;
|
|
12
|
+
justify-content: space-between;
|
|
13
|
+
align-items: center;
|
|
14
|
+
padding: 1rem 2rem;
|
|
15
|
+
background: #111;
|
|
16
|
+
border-bottom: 1px solid #222;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.navBrand {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.logo {
|
|
25
|
+
font-size: 1.25rem;
|
|
26
|
+
font-weight: 700;
|
|
27
|
+
color: #00d9ff;
|
|
28
|
+
text-decoration: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.logo:hover {
|
|
32
|
+
opacity: 1;
|
|
33
|
+
color: #00d9ff;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.navLinks {
|
|
37
|
+
display: flex;
|
|
38
|
+
gap: 1.5rem;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.navLink {
|
|
42
|
+
color: #888;
|
|
43
|
+
font-weight: 500;
|
|
44
|
+
text-decoration: none;
|
|
45
|
+
transition: color 0.2s;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.navLink:hover {
|
|
49
|
+
color: #fff;
|
|
50
|
+
opacity: 1;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.navLinkActive {
|
|
54
|
+
color: #fff;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Main Content */
|
|
58
|
+
.main {
|
|
59
|
+
flex: 1;
|
|
60
|
+
padding: 2rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.container {
|
|
64
|
+
max-width: 1000px;
|
|
65
|
+
margin: 0 auto;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Hero Section */
|
|
69
|
+
.hero {
|
|
70
|
+
text-align: center;
|
|
71
|
+
margin-bottom: 3rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.title {
|
|
75
|
+
font-size: 3rem;
|
|
76
|
+
font-weight: 700;
|
|
77
|
+
margin-bottom: 0.5rem;
|
|
78
|
+
background: linear-gradient(135deg, #fff 0%, #888 100%);
|
|
79
|
+
-webkit-background-clip: text;
|
|
80
|
+
-webkit-text-fill-color: transparent;
|
|
81
|
+
background-clip: text;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.subtitle {
|
|
85
|
+
color: #888;
|
|
86
|
+
font-size: 1.25rem;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Cards Grid */
|
|
90
|
+
.cards {
|
|
91
|
+
display: grid;
|
|
92
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
93
|
+
gap: 1.5rem;
|
|
94
|
+
margin-top: 2rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.card {
|
|
98
|
+
background: #111;
|
|
99
|
+
border: 1px solid #222;
|
|
100
|
+
border-radius: 12px;
|
|
101
|
+
padding: 1.5rem;
|
|
102
|
+
transition: border-color 0.2s, transform 0.2s;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.card:hover {
|
|
106
|
+
border-color: #333;
|
|
107
|
+
transform: translateY(-2px);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.card h2 {
|
|
111
|
+
font-size: 1.1rem;
|
|
112
|
+
color: #fff;
|
|
113
|
+
margin-bottom: 1rem;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.card p {
|
|
117
|
+
color: #888;
|
|
118
|
+
font-size: 0.95rem;
|
|
119
|
+
margin-bottom: 0.5rem;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.card a {
|
|
123
|
+
display: inline-block;
|
|
124
|
+
margin-top: 0.25rem;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* Status Indicators */
|
|
128
|
+
.loading {
|
|
129
|
+
color: #888;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.success {
|
|
133
|
+
color: #00d9ff;
|
|
134
|
+
font-weight: 600;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.error {
|
|
138
|
+
color: #ff4444;
|
|
139
|
+
font-weight: 600;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.meta {
|
|
143
|
+
font-size: 0.8rem;
|
|
144
|
+
color: #666;
|
|
145
|
+
margin-top: 0.5rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* Auth Card */
|
|
149
|
+
.authCard {
|
|
150
|
+
background: #111;
|
|
151
|
+
border: 1px solid #222;
|
|
152
|
+
border-radius: 12px;
|
|
153
|
+
padding: 2rem;
|
|
154
|
+
max-width: 400px;
|
|
155
|
+
margin: 0 auto;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.authTabs {
|
|
159
|
+
display: flex;
|
|
160
|
+
margin-bottom: 1.5rem;
|
|
161
|
+
border-bottom: 1px solid #222;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.authTab {
|
|
165
|
+
flex: 1;
|
|
166
|
+
padding: 0.75rem;
|
|
167
|
+
background: transparent;
|
|
168
|
+
border: none;
|
|
169
|
+
color: #666;
|
|
170
|
+
font-size: 1rem;
|
|
171
|
+
cursor: pointer;
|
|
172
|
+
transition: color 0.2s;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.authTab:hover {
|
|
176
|
+
color: #888;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.authTabActive {
|
|
180
|
+
color: #fff;
|
|
181
|
+
border-bottom: 2px solid #00d9ff;
|
|
182
|
+
margin-bottom: -1px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* Forms */
|
|
186
|
+
.form {
|
|
187
|
+
display: flex;
|
|
188
|
+
flex-direction: column;
|
|
189
|
+
gap: 1rem;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.input {
|
|
193
|
+
padding: 0.875rem 1rem;
|
|
194
|
+
background: #0a0a0a;
|
|
195
|
+
border: 1px solid #333;
|
|
196
|
+
border-radius: 8px;
|
|
197
|
+
color: #fff;
|
|
198
|
+
font-size: 1rem;
|
|
199
|
+
transition: border-color 0.2s;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.input:focus {
|
|
203
|
+
outline: none;
|
|
204
|
+
border-color: #00d9ff;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.input::placeholder {
|
|
208
|
+
color: #555;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.button {
|
|
212
|
+
padding: 0.875rem 1.5rem;
|
|
213
|
+
background: #00d9ff;
|
|
214
|
+
color: #000;
|
|
215
|
+
border: none;
|
|
216
|
+
border-radius: 8px;
|
|
217
|
+
font-size: 1rem;
|
|
218
|
+
font-weight: 600;
|
|
219
|
+
cursor: pointer;
|
|
220
|
+
transition: opacity 0.2s, transform 0.1s;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.button:hover {
|
|
224
|
+
opacity: 0.9;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.button:active {
|
|
228
|
+
transform: scale(0.98);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.button:disabled {
|
|
232
|
+
opacity: 0.5;
|
|
233
|
+
cursor: not-allowed;
|
|
234
|
+
transform: none;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.formError {
|
|
238
|
+
color: #ff4444;
|
|
239
|
+
font-size: 0.9rem;
|
|
240
|
+
text-align: center;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.formHint {
|
|
244
|
+
color: #666;
|
|
245
|
+
font-size: 0.85rem;
|
|
246
|
+
text-align: center;
|
|
247
|
+
margin-top: 0.5rem;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/* Responsive */
|
|
251
|
+
@media (max-width: 768px) {
|
|
252
|
+
.nav {
|
|
253
|
+
padding: 1rem;
|
|
254
|
+
flex-direction: column;
|
|
255
|
+
gap: 1rem;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.navLinks {
|
|
259
|
+
width: 100%;
|
|
260
|
+
justify-content: center;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.main {
|
|
264
|
+
padding: 1rem;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.title {
|
|
268
|
+
font-size: 2rem;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.subtitle {
|
|
272
|
+
font-size: 1rem;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.cards {
|
|
276
|
+
grid-template-columns: 1fr;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.authCard {
|
|
280
|
+
padding: 1.5rem;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="128" height="128" rx="20" fill="url(#paint0_linear_8_2)"/>
|
|
3
|
+
<path d="M29 62L64 113L99 62" stroke="white" stroke-width="14" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<path d="M38 39L64 77L90 39" stroke="white" stroke-opacity="0.5" stroke-width="14" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5
|
+
<path d="M45 13L64 41L83 13" stroke="white" stroke-opacity="0.2" stroke-width="14" stroke-linecap="round" stroke-linejoin="round"/>
|
|
6
|
+
<defs>
|
|
7
|
+
<linearGradient id="paint0_linear_8_2" x1="0" y1="0" x2="128" y2="128" gradientUnits="userSpaceOnUse">
|
|
8
|
+
<stop offset="0.336538" stop-color="#3178C6"/>
|
|
9
|
+
<stop offset="1" stop-color="#3297B1"/>
|
|
10
|
+
</linearGradient>
|
|
11
|
+
</defs>
|
|
12
|
+
</svg>
|