@vertz/create-vertz-app 0.2.41 → 0.2.42
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/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +6 -1
- package/dist/templates/index.d.ts +13 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +167 -11
- package/package.json +1 -1
package/dist/scaffold.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,WAAW,EAAE,MAAM;CAIhC;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBzF"}
|
package/dist/scaffold.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { apiDevelopmentRuleTemplate, appComponentTemplate, bunfigTemplate, bunPluginShimTemplate, claudeMdTemplate, clientTemplate, dbTemplate, entryClientTemplate, envExampleTemplate, envModuleTemplate, envTemplate, faviconTemplate, gitignoreTemplate, helloWorldAppTemplate, helloWorldClaudeMdTemplate, helloWorldHomePageTemplate, helloWorldPackageJsonTemplate, helloWorldVertzConfigTemplate, homePageTemplate, packageJsonTemplate, schemaTemplate, serverTemplate, tasksEntityTemplate, themeTemplate, tsconfigTemplate, uiDevelopmentRuleTemplate, vertzConfigTemplate, } from './templates/index.js';
|
|
3
|
+
import { apiDevelopmentRuleTemplate, appComponentTemplate, bunfigTemplate, bunPluginShimTemplate, claudeMdTemplate, clientTemplate, dbTemplate, entryClientTemplate, envExampleTemplate, envModuleTemplate, envTemplate, faviconTemplate, gitignoreTemplate, helloWorldAboutPageTemplate, helloWorldAppTemplate, helloWorldClaudeMdTemplate, helloWorldHomePageTemplate, helloWorldNavBarTemplate, helloWorldPackageJsonTemplate, helloWorldRouterTemplate, helloWorldVertzConfigTemplate, homePageTemplate, packageJsonTemplate, schemaTemplate, serverTemplate, tasksEntityTemplate, themeTemplate, tsconfigTemplate, uiDevelopmentRuleTemplate, vertzConfigTemplate, } from './templates/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Error thrown when the project directory already exists
|
|
6
6
|
*/
|
|
@@ -42,11 +42,13 @@ export async function scaffold(parentDir, options) {
|
|
|
42
42
|
async function scaffoldHelloWorld(projectDir, projectName) {
|
|
43
43
|
const srcDir = path.join(projectDir, 'src');
|
|
44
44
|
const pagesDir = path.join(srcDir, 'pages');
|
|
45
|
+
const componentsDir = path.join(srcDir, 'components');
|
|
45
46
|
const stylesDir = path.join(srcDir, 'styles');
|
|
46
47
|
const claudeRulesDir = path.join(projectDir, '.claude', 'rules');
|
|
47
48
|
const publicDir = path.join(projectDir, 'public');
|
|
48
49
|
await Promise.all([
|
|
49
50
|
fs.mkdir(pagesDir, { recursive: true }),
|
|
51
|
+
fs.mkdir(componentsDir, { recursive: true }),
|
|
50
52
|
fs.mkdir(stylesDir, { recursive: true }),
|
|
51
53
|
fs.mkdir(claudeRulesDir, { recursive: true }),
|
|
52
54
|
fs.mkdir(publicDir, { recursive: true }),
|
|
@@ -62,7 +64,10 @@ async function scaffoldHelloWorld(projectDir, projectName) {
|
|
|
62
64
|
// UI source files
|
|
63
65
|
writeFile(srcDir, 'app.tsx', helloWorldAppTemplate()),
|
|
64
66
|
writeFile(srcDir, 'entry-client.ts', entryClientTemplate()),
|
|
67
|
+
writeFile(srcDir, 'router.tsx', helloWorldRouterTemplate()),
|
|
65
68
|
writeFile(pagesDir, 'home.tsx', helloWorldHomePageTemplate()),
|
|
69
|
+
writeFile(pagesDir, 'about.tsx', helloWorldAboutPageTemplate()),
|
|
70
|
+
writeFile(componentsDir, 'nav-bar.tsx', helloWorldNavBarTemplate()),
|
|
66
71
|
writeFile(stylesDir, 'theme.ts', themeTemplate()),
|
|
67
72
|
// Static assets
|
|
68
73
|
writeFile(publicDir, 'favicon.svg', faviconTemplate()),
|
|
@@ -101,7 +101,7 @@ export declare function helloWorldPackageJsonTemplate(projectName: string): stri
|
|
|
101
101
|
*/
|
|
102
102
|
export declare function helloWorldVertzConfigTemplate(): string;
|
|
103
103
|
/**
|
|
104
|
-
* src/app.tsx for hello-world —
|
|
104
|
+
* src/app.tsx for hello-world — App with RouterContext.Provider, RouterView, and NavBar
|
|
105
105
|
*/
|
|
106
106
|
export declare function helloWorldAppTemplate(): string;
|
|
107
107
|
/**
|
|
@@ -109,4 +109,16 @@ export declare function helloWorldAppTemplate(): string;
|
|
|
109
109
|
* the Vertz compiler's signal transformation (let → signal)
|
|
110
110
|
*/
|
|
111
111
|
export declare function helloWorldHomePageTemplate(): string;
|
|
112
|
+
/**
|
|
113
|
+
* src/router.tsx for hello-world — route definitions + router instance
|
|
114
|
+
*/
|
|
115
|
+
export declare function helloWorldRouterTemplate(): string;
|
|
116
|
+
/**
|
|
117
|
+
* src/pages/about.tsx for hello-world — simple second page
|
|
118
|
+
*/
|
|
119
|
+
export declare function helloWorldAboutPageTemplate(): string;
|
|
120
|
+
/**
|
|
121
|
+
* src/components/nav-bar.tsx for hello-world — navigation with Link
|
|
122
|
+
*/
|
|
123
|
+
export declare function helloWorldNavBarTemplate(): string;
|
|
112
124
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CA+C5D;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CA+KnD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAwSlD;AAID;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAID;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CA4B/D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAoBzC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAa5C;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAIpC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAIvC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAc9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CA6B1C;AAID;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAW1C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAoBvC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAavC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAWnC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAe5C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAOvC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAgD7C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAW5C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CActC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAmLzC;AAID;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAmCtE;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAsBzE;AAED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAItD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA0C9C;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CA4BnD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAgBjD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAwBpD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA+BjD"}
|
package/dist/templates/index.js
CHANGED
|
@@ -30,6 +30,24 @@ The dev server automatically runs codegen and migrations when files change.
|
|
|
30
30
|
- Refer to https://docs.vertz.dev for full framework documentation
|
|
31
31
|
- Entity files use the \`.entity.ts\` suffix
|
|
32
32
|
- The Vertz compiler handles all reactivity — never use \`.value\`, \`signal()\`, or \`computed()\` manually
|
|
33
|
+
|
|
34
|
+
## Auto-Generated SDK
|
|
35
|
+
|
|
36
|
+
Vertz auto-generates a fully typed SDK at \`.vertz/generated/\` from your entity and service definitions.
|
|
37
|
+
The SDK is re-exported from \`src/client.ts\` as \`api\`. Use it for ALL data fetching and mutations.
|
|
38
|
+
|
|
39
|
+
**NEVER use raw \`fetch()\` for API calls.** Always use the generated SDK methods with \`query()\` and \`form()\`:
|
|
40
|
+
|
|
41
|
+
\`\`\`ts
|
|
42
|
+
import { api } from './client'; // auto-generated typed SDK
|
|
43
|
+
import { query, form } from 'vertz/ui';
|
|
44
|
+
|
|
45
|
+
const tasks = query(api.tasks.list()); // entity CRUD
|
|
46
|
+
const contactForm = form(api.support.send); // service action
|
|
47
|
+
\`\`\`
|
|
48
|
+
|
|
49
|
+
Raw \`fetch()\` bypasses type safety, SSR integration, caching, and optimistic updates.
|
|
50
|
+
The SDK runs codegen automatically during \`bun run dev\` and \`bun run build\`.
|
|
33
51
|
`;
|
|
34
52
|
}
|
|
35
53
|
/**
|
|
@@ -117,6 +135,28 @@ Each entity automatically provides these operations:
|
|
|
117
135
|
| \`update\` | PATCH /api/<entity>/:id | Update existing record |
|
|
118
136
|
| \`delete\` | DELETE /api/<entity>/:id| Delete record |
|
|
119
137
|
|
|
138
|
+
## Auto-Generated SDK
|
|
139
|
+
|
|
140
|
+
Entities and services automatically generate a typed SDK at \`.vertz/generated/\`.
|
|
141
|
+
The SDK is consumed in the UI via \`src/client.ts\`:
|
|
142
|
+
|
|
143
|
+
\`\`\`ts
|
|
144
|
+
import { api } from '../client';
|
|
145
|
+
|
|
146
|
+
// Entity CRUD — auto-generated from entity('posts', ...)
|
|
147
|
+
api.posts.list();
|
|
148
|
+
api.posts.get(id);
|
|
149
|
+
api.posts.create({ title: 'Hello' });
|
|
150
|
+
api.posts.update(id, { title: 'Updated' });
|
|
151
|
+
api.posts.delete(id);
|
|
152
|
+
|
|
153
|
+
// Service actions — auto-generated from service('notifications', ...)
|
|
154
|
+
api.notifications.sendEmail({ to, subject, body });
|
|
155
|
+
\`\`\`
|
|
156
|
+
|
|
157
|
+
The SDK provides full type safety, SSR integration, caching, and optimistic updates.
|
|
158
|
+
**NEVER use raw \`fetch()\` in UI code — always use the SDK.**
|
|
159
|
+
|
|
120
160
|
## Server Configuration
|
|
121
161
|
|
|
122
162
|
Register all entities with \`createServer\`:
|
|
@@ -205,6 +245,26 @@ import { css, query, globalCss, ThemeProvider, variants } from 'vertz/ui';
|
|
|
205
245
|
import { api } from '../client';
|
|
206
246
|
\`\`\`
|
|
207
247
|
|
|
248
|
+
## IMPORTANT: Always Use the Generated SDK
|
|
249
|
+
|
|
250
|
+
The \`api\` import from \`'../client'\` is a typed SDK auto-generated from your entity and service definitions.
|
|
251
|
+
It provides typed methods for every entity CRUD operation and service action.
|
|
252
|
+
|
|
253
|
+
**NEVER use raw \`fetch()\` for API calls.** Raw fetch bypasses:
|
|
254
|
+
- Type safety (request/response types)
|
|
255
|
+
- SSR data loading (causes loading flash)
|
|
256
|
+
- Automatic cache invalidation
|
|
257
|
+
- Optimistic updates
|
|
258
|
+
|
|
259
|
+
\`\`\`tsx
|
|
260
|
+
// WRONG — raw fetch
|
|
261
|
+
const res = await fetch('/api/tasks');
|
|
262
|
+
const tasks = await res.json();
|
|
263
|
+
|
|
264
|
+
// RIGHT — use the auto-generated SDK
|
|
265
|
+
const tasks = query(api.tasks.list());
|
|
266
|
+
\`\`\`
|
|
267
|
+
|
|
208
268
|
## Components
|
|
209
269
|
|
|
210
270
|
### Destructure props in parameters
|
|
@@ -503,7 +563,6 @@ export function packageJsonTemplate(projectName) {
|
|
|
503
563
|
},
|
|
504
564
|
devDependencies: {
|
|
505
565
|
'@vertz/cli': '^0.2.0',
|
|
506
|
-
'@vertz/ui-compiler': '^0.2.0',
|
|
507
566
|
'bun-types': '^1.0.0',
|
|
508
567
|
typescript: '^5.8.0',
|
|
509
568
|
},
|
|
@@ -1025,6 +1084,11 @@ bun run build # Production build
|
|
|
1025
1084
|
|
|
1026
1085
|
To add API and database support, see https://docs.vertz.dev/guides/server/overview
|
|
1027
1086
|
|
|
1087
|
+
## Routing
|
|
1088
|
+
|
|
1089
|
+
Routes are defined in \`src/router.tsx\` using \`defineRoutes\` and \`createRouter\`.
|
|
1090
|
+
To add a new page, create a component in \`src/pages/\` and add a route entry in \`src/router.tsx\`.
|
|
1091
|
+
|
|
1028
1092
|
## Conventions
|
|
1029
1093
|
|
|
1030
1094
|
- See \`.claude/rules/\` for UI development conventions
|
|
@@ -1051,7 +1115,6 @@ export function helloWorldPackageJsonTemplate(projectName) {
|
|
|
1051
1115
|
},
|
|
1052
1116
|
devDependencies: {
|
|
1053
1117
|
'@vertz/cli': '^0.2.0',
|
|
1054
|
-
'@vertz/ui-compiler': '^0.2.0',
|
|
1055
1118
|
'bun-types': '^1.0.0',
|
|
1056
1119
|
typescript: '^5.8.0',
|
|
1057
1120
|
},
|
|
@@ -1067,12 +1130,13 @@ export default {};
|
|
|
1067
1130
|
`;
|
|
1068
1131
|
}
|
|
1069
1132
|
/**
|
|
1070
|
-
* src/app.tsx for hello-world —
|
|
1133
|
+
* src/app.tsx for hello-world — App with RouterContext.Provider, RouterView, and NavBar
|
|
1071
1134
|
*/
|
|
1072
1135
|
export function helloWorldAppTemplate() {
|
|
1073
|
-
return `import { css, getInjectedCSS, globalCss, ThemeProvider } from 'vertz/ui';
|
|
1074
|
-
import {
|
|
1136
|
+
return `import { css, getInjectedCSS, globalCss, RouterContext, RouterView, ThemeProvider } from 'vertz/ui';
|
|
1137
|
+
import { appRouter } from './router';
|
|
1075
1138
|
import { appTheme, themeGlobals } from './styles/theme';
|
|
1139
|
+
import { NavBar } from './components/nav-bar';
|
|
1076
1140
|
|
|
1077
1141
|
const appGlobals = globalCss({
|
|
1078
1142
|
a: {
|
|
@@ -1083,6 +1147,7 @@ const appGlobals = globalCss({
|
|
|
1083
1147
|
|
|
1084
1148
|
const styles = css({
|
|
1085
1149
|
shell: ['min-h:screen', 'bg:background', 'text:foreground'],
|
|
1150
|
+
main: ['max-w:2xl', 'mx:auto', 'px:6', 'py:8'],
|
|
1086
1151
|
});
|
|
1087
1152
|
|
|
1088
1153
|
export { getInjectedCSS };
|
|
@@ -1092,11 +1157,19 @@ export const globalStyles = [themeGlobals.css, appGlobals.css];
|
|
|
1092
1157
|
export function App() {
|
|
1093
1158
|
return (
|
|
1094
1159
|
<div data-testid="app-root">
|
|
1095
|
-
<
|
|
1096
|
-
<
|
|
1097
|
-
<
|
|
1098
|
-
|
|
1099
|
-
|
|
1160
|
+
<RouterContext.Provider value={appRouter}>
|
|
1161
|
+
<ThemeProvider theme="light">
|
|
1162
|
+
<div className={styles.shell}>
|
|
1163
|
+
<NavBar />
|
|
1164
|
+
<main className={styles.main}>
|
|
1165
|
+
<RouterView
|
|
1166
|
+
router={appRouter}
|
|
1167
|
+
fallback={() => <div>Page not found</div>}
|
|
1168
|
+
/>
|
|
1169
|
+
</main>
|
|
1170
|
+
</div>
|
|
1171
|
+
</ThemeProvider>
|
|
1172
|
+
</RouterContext.Provider>
|
|
1100
1173
|
</div>
|
|
1101
1174
|
);
|
|
1102
1175
|
}
|
|
@@ -1111,7 +1184,7 @@ export function helloWorldHomePageTemplate() {
|
|
|
1111
1184
|
import { Button } from '@vertz/ui/components';
|
|
1112
1185
|
|
|
1113
1186
|
const styles = css({
|
|
1114
|
-
container: ['flex', 'flex-col', 'items:center', 'justify:center', '
|
|
1187
|
+
container: ['flex', 'flex-col', 'items:center', 'justify:center', 'py:16', 'gap:6'],
|
|
1115
1188
|
title: ['font:4xl', 'font:bold', 'text:foreground'],
|
|
1116
1189
|
subtitle: ['text:muted-foreground', 'text:lg'],
|
|
1117
1190
|
count: ['font:6xl', 'font:bold', 'text:primary'],
|
|
@@ -1135,3 +1208,86 @@ export function HomePage() {
|
|
|
1135
1208
|
}
|
|
1136
1209
|
`;
|
|
1137
1210
|
}
|
|
1211
|
+
/**
|
|
1212
|
+
* src/router.tsx for hello-world — route definitions + router instance
|
|
1213
|
+
*/
|
|
1214
|
+
export function helloWorldRouterTemplate() {
|
|
1215
|
+
return `import { createRouter, defineRoutes } from 'vertz/ui';
|
|
1216
|
+
import { HomePage } from './pages/home';
|
|
1217
|
+
import { AboutPage } from './pages/about';
|
|
1218
|
+
|
|
1219
|
+
export const routes = defineRoutes({
|
|
1220
|
+
'/': {
|
|
1221
|
+
component: () => <HomePage />,
|
|
1222
|
+
},
|
|
1223
|
+
'/about': {
|
|
1224
|
+
component: () => <AboutPage />,
|
|
1225
|
+
},
|
|
1226
|
+
});
|
|
1227
|
+
|
|
1228
|
+
export const appRouter = createRouter(routes);
|
|
1229
|
+
`;
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* src/pages/about.tsx for hello-world — simple second page
|
|
1233
|
+
*/
|
|
1234
|
+
export function helloWorldAboutPageTemplate() {
|
|
1235
|
+
return `import { css } from 'vertz/ui';
|
|
1236
|
+
|
|
1237
|
+
const styles = css({
|
|
1238
|
+
container: ['flex', 'flex-col', 'items:center', 'justify:center', 'py:16', 'gap:4'],
|
|
1239
|
+
title: ['font:3xl', 'font:bold', 'text:foreground'],
|
|
1240
|
+
text: ['text:muted-foreground', 'text:lg', 'max-w:lg', 'text:center'],
|
|
1241
|
+
code: ['font:mono', 'bg:muted', 'px:2', 'py:1', 'rounded:sm', 'text:sm'],
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
export function AboutPage() {
|
|
1245
|
+
return (
|
|
1246
|
+
<div className={styles.container} data-testid="about-page">
|
|
1247
|
+
<h1 className={styles.title}>About</h1>
|
|
1248
|
+
<p className={styles.text}>
|
|
1249
|
+
This app was built with Vertz — a type-safe, LLM-native framework.
|
|
1250
|
+
</p>
|
|
1251
|
+
<p className={styles.text}>
|
|
1252
|
+
Edit this page at <code className={styles.code}>src/pages/about.tsx</code>
|
|
1253
|
+
</p>
|
|
1254
|
+
</div>
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
`;
|
|
1258
|
+
}
|
|
1259
|
+
/**
|
|
1260
|
+
* src/components/nav-bar.tsx for hello-world — navigation with Link
|
|
1261
|
+
*/
|
|
1262
|
+
export function helloWorldNavBarTemplate() {
|
|
1263
|
+
return `import { css, Link } from 'vertz/ui';
|
|
1264
|
+
|
|
1265
|
+
const styles = css({
|
|
1266
|
+
nav: [
|
|
1267
|
+
'flex',
|
|
1268
|
+
'items:center',
|
|
1269
|
+
'justify:between',
|
|
1270
|
+
'px:6',
|
|
1271
|
+
'py:4',
|
|
1272
|
+
'border-b:1',
|
|
1273
|
+
'border:border',
|
|
1274
|
+
],
|
|
1275
|
+
brand: ['font:lg', 'font:bold', 'text:foreground'],
|
|
1276
|
+
links: ['flex', 'gap:4'],
|
|
1277
|
+
link: ['text:sm', 'text:muted-foreground', 'hover:text:foreground', 'transition:colors'],
|
|
1278
|
+
active: ['text:foreground', 'font:medium'],
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
export function NavBar() {
|
|
1282
|
+
return (
|
|
1283
|
+
<nav className={styles.nav}>
|
|
1284
|
+
<div className={styles.brand}>My Vertz App</div>
|
|
1285
|
+
<div className={styles.links}>
|
|
1286
|
+
<Link href="/" className={styles.link} activeClass={styles.active}>Home</Link>
|
|
1287
|
+
<Link href="/about" className={styles.link} activeClass={styles.active}>About</Link>
|
|
1288
|
+
</div>
|
|
1289
|
+
</nav>
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
`;
|
|
1293
|
+
}
|