create-omg 0.4.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +14 -0
  2. package/dist/index.mjs +100 -0
  3. package/dist/template/AGENTS.md +49 -0
  4. package/dist/template/README.md +18 -0
  5. package/dist/template/_gitignore +24 -0
  6. package/dist/template/bun.lock +898 -0
  7. package/dist/template/eslint.config.js +23 -0
  8. package/dist/template/functions/.gitkeep +0 -0
  9. package/dist/template/index.html +20 -0
  10. package/dist/template/package.json +48 -0
  11. package/dist/template/public/favicon.svg +1 -0
  12. package/dist/template/public/icons/apple-touch-icon.png +0 -0
  13. package/dist/template/public/icons/pwa-192x192.png +0 -0
  14. package/dist/template/public/icons/pwa-512x512-maskable.png +0 -0
  15. package/dist/template/public/icons/pwa-512x512.png +0 -0
  16. package/dist/template/public/icons.svg +24 -0
  17. package/dist/template/schema.ts +5 -0
  18. package/dist/template/server/db.ts +103 -0
  19. package/dist/template/src/App.tsx +128 -0
  20. package/dist/template/src/components/ui/animated-number.tsx +102 -0
  21. package/dist/template/src/components/ui/animated-text.tsx +109 -0
  22. package/dist/template/src/components/ui/bottom-nav.tsx +131 -0
  23. package/dist/template/src/components/ui/button.tsx +84 -0
  24. package/dist/template/src/components/ui/card.tsx +70 -0
  25. package/dist/template/src/components/ui/otp-input.tsx +179 -0
  26. package/dist/template/src/components/ui/scroll-affordance.tsx +106 -0
  27. package/dist/template/src/components/ui/sound.ts +182 -0
  28. package/dist/template/src/components/ui/transitions.tsx +419 -0
  29. package/dist/template/src/components/ui/vibes-ui-styles.ts +388 -0
  30. package/dist/template/src/db.drizzle.ts +5 -0
  31. package/dist/template/src/index.css +1 -0
  32. package/dist/template/src/lib/utils.ts +6 -0
  33. package/dist/template/src/main.tsx +10 -0
  34. package/dist/template/tsconfig.app.json +30 -0
  35. package/dist/template/tsconfig.json +10 -0
  36. package/dist/template/tsconfig.node.json +24 -0
  37. package/dist/template/vite.config.ts +23 -0
  38. package/package.json +37 -0
@@ -0,0 +1,388 @@
1
+ // Delight-primitive stylesheet — injected once at first mount.
2
+ //
3
+ // Vendored source (was @omg-dev/ui). These primitives ship plain, namespaced
4
+ // (`.vui-*`) CSS in a single injected `<style>` tag rather than Tailwind
5
+ // utility classes. That's deliberate and survives `shadcn init` rewriting
6
+ // `index.css` at bake time: the styles live here in a `.ts` module nothing
7
+ // else touches, so there's no `@source` hack and no reliance on Tailwind's
8
+ // content scan. The text/number primitives INHERIT the surrounding text color
9
+ // (so they sit correctly on any surface — a dark card, a colored hero — and
10
+ // honor a text-* utility you put on them). The standalone scroll cue reads
11
+ // --muted-foreground with a neutral prefers-color-scheme fallback for a bare,
12
+ // unthemed app. Edit the CSS below freely; it's yours now.
13
+
14
+ export const STYLE_ID = "vibes-ui-styles"
15
+
16
+ export function ensureStyles() {
17
+ if (typeof document === "undefined") return
18
+ if (document.getElementById(STYLE_ID)) return
19
+ const el = document.createElement("style")
20
+ el.id = STYLE_ID
21
+ el.textContent = CSS
22
+ document.head.appendChild(el)
23
+ }
24
+
25
+ const CSS = `
26
+ .vui {
27
+ /* Only the scroll cue still needs a bare-app fallback (--muted-foreground).
28
+ The text/number primitives inherit their color now, so no --vui-fg. */
29
+ --vui-muted: #71717a;
30
+ /* Shared transition tokens for the <Transitions> family (.vui-t-*). Soft,
31
+ fast-out eases; tune these in one place. */
32
+ --vui-ease-soft: cubic-bezier(0.22, 1, 0.36, 1);
33
+ --vui-ease-bounce: cubic-bezier(0.34, 1.36, 0.64, 1);
34
+ font-family: inherit;
35
+ }
36
+ @media (prefers-color-scheme: dark) {
37
+ .vui {
38
+ --vui-muted: #a1a1aa;
39
+ }
40
+ }
41
+
42
+ /* ── AnimatedNumber — odometer / slot-text rolling digits ──────────────── */
43
+ .vui-num {
44
+ display: inline-flex;
45
+ align-items: baseline;
46
+ /* No \`color\` here on purpose: inherit the surrounding text color (or honor a
47
+ text-* utility on the element) like normal inline text. Pinning this to
48
+ var(--foreground) made the number render page-foreground-dark even on a
49
+ dark card / colored surface, where its siblings (which inherit) sit light —
50
+ a dark-on-dark theme conflict. */
51
+ font-variant-numeric: tabular-nums;
52
+ line-height: 1;
53
+ }
54
+ .vui-num-reel {
55
+ position: relative;
56
+ display: inline-block;
57
+ height: 1em;
58
+ overflow: hidden;
59
+ vertical-align: bottom;
60
+ }
61
+ .vui-num-track {
62
+ display: flex;
63
+ flex-direction: column;
64
+ /* The roll itself. Long, soft ease so digits settle like an odometer.
65
+ transform is set inline per-digit; the per-position stagger (delay) is
66
+ set inline too so significant digits cascade in after the small ones. */
67
+ transition: transform 0.85s cubic-bezier(0.22, 1, 0.36, 1);
68
+ will-change: transform;
69
+ }
70
+ .vui-num-cell {
71
+ height: 1em;
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ }
76
+ .vui-num-sym {
77
+ display: inline-block;
78
+ }
79
+ @media (prefers-reduced-motion: reduce) {
80
+ .vui-num-track { transition: none; }
81
+ }
82
+
83
+ /* ── AnimatedText — split-flap / slot-text rolling letters ────────────── */
84
+ .vui-text {
85
+ display: inline-flex;
86
+ align-items: baseline;
87
+ /* Inherit the surrounding text color (or honor a text-* utility) — see the
88
+ note on .vui-num. Don't pin to var(--foreground): it overrode the color of
89
+ whatever surface the text sits on. */
90
+ line-height: 1;
91
+ white-space: pre;
92
+ }
93
+ .vui-text-reel {
94
+ position: relative;
95
+ display: inline-block;
96
+ /* Fixed character cell — every reel is as wide as the alphabet's widest
97
+ glyph, so the row reads like a split-flap board and never reflows mid-roll. */
98
+ height: 1em;
99
+ overflow: hidden;
100
+ vertical-align: bottom;
101
+ }
102
+ .vui-text-track {
103
+ display: flex;
104
+ flex-direction: column;
105
+ /* The roll itself. Long, soft ease so letters settle like a flap board.
106
+ transform is set inline per-letter; the per-position stagger (delay) is
107
+ set inline too so the word reveals left-to-right. */
108
+ transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
109
+ will-change: transform;
110
+ }
111
+ .vui-text-cell {
112
+ height: 1em;
113
+ display: flex;
114
+ align-items: center;
115
+ justify-content: center;
116
+ white-space: pre;
117
+ }
118
+ .vui-text-sym {
119
+ display: inline-block;
120
+ white-space: pre;
121
+ }
122
+ @media (prefers-reduced-motion: reduce) {
123
+ .vui-text-track { transition: none; }
124
+ }
125
+
126
+ /* ── ScrollAffordance — "there's more below" cue ──────────────────────── */
127
+ .vui-scroll {
128
+ display: inline-flex;
129
+ flex-direction: column;
130
+ align-items: center;
131
+ gap: 6px;
132
+ color: var(--muted-foreground, var(--vui-muted));
133
+ font-size: 12px;
134
+ font-weight: 500;
135
+ letter-spacing: 0.02em;
136
+ /* Fade + lift away the instant the user starts scrolling — the cue has
137
+ done its job, lingering would be noise. */
138
+ transition: opacity 0.4s ease, transform 0.4s ease;
139
+ pointer-events: none;
140
+ user-select: none;
141
+ }
142
+ .vui-scroll[data-hidden="true"] {
143
+ opacity: 0;
144
+ transform: translateY(6px);
145
+ }
146
+ .vui-scroll-chevron {
147
+ width: 22px;
148
+ height: 22px;
149
+ animation: vui-bob 1.8s ease-in-out infinite;
150
+ }
151
+ @keyframes vui-bob {
152
+ 0%, 100% { transform: translateY(0); opacity: 0.65; }
153
+ 50% { transform: translateY(4px); opacity: 1; }
154
+ }
155
+ @media (prefers-reduced-motion: reduce) {
156
+ .vui-scroll-chevron { animation: none; }
157
+ .vui-scroll { transition: none; }
158
+ }
159
+
160
+ /* ── Transitions (transitions.dev, vendored) ──────────────────────────────
161
+ Dependency-free, CSS-only micro-interactions. Only transform/opacity/filter
162
+ animate (never color/size/shadow), close is faster than open, and every
163
+ family carries a prefers-reduced-motion guard. Driven by the React wrappers
164
+ in transitions.tsx via .is-open / .is-closing / data-* state. */
165
+
166
+ /* Modal — dialog open/close (+ optional fading backdrop) */
167
+ .vui-t-modal {
168
+ transform-origin: center;
169
+ transform: scale(0.95);
170
+ opacity: 0;
171
+ pointer-events: none;
172
+ transition:
173
+ transform 300ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
174
+ opacity 300ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
175
+ will-change: transform, opacity;
176
+ }
177
+ .vui-t-modal.is-open { transform: scale(1); opacity: 1; pointer-events: auto; }
178
+ .vui-t-modal.is-closing {
179
+ transform: scale(0.96);
180
+ opacity: 0;
181
+ pointer-events: none;
182
+ transition:
183
+ transform 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
184
+ opacity 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
185
+ }
186
+ .vui-t-backdrop {
187
+ opacity: 0;
188
+ transition: opacity 300ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
189
+ }
190
+ .vui-t-backdrop.is-open { opacity: 1; }
191
+ .vui-t-backdrop.is-closing {
192
+ opacity: 0;
193
+ transition: opacity 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
194
+ }
195
+
196
+ /* Menu — popover/dropdown anchored to its trigger (set data-origin) */
197
+ .vui-t-menu {
198
+ transform-origin: top left;
199
+ transform: scale(0.97);
200
+ opacity: 0;
201
+ pointer-events: none;
202
+ transition:
203
+ transform 250ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
204
+ opacity 250ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
205
+ will-change: transform, opacity;
206
+ }
207
+ .vui-t-menu[data-origin="top-right"] { transform-origin: top right; }
208
+ .vui-t-menu[data-origin="top-center"] { transform-origin: top center; }
209
+ .vui-t-menu[data-origin="bottom-left"] { transform-origin: bottom left; }
210
+ .vui-t-menu[data-origin="bottom-center"] { transform-origin: bottom center; }
211
+ .vui-t-menu[data-origin="bottom-right"] { transform-origin: bottom right; }
212
+ .vui-t-menu.is-open { transform: scale(1); opacity: 1; pointer-events: auto; }
213
+ .vui-t-menu.is-closing {
214
+ transform: scale(0.99);
215
+ opacity: 0;
216
+ pointer-events: none;
217
+ transition:
218
+ transform 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
219
+ opacity 150ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
220
+ }
221
+
222
+ /* Panel — inline reveal / drawer / expander (stays mounted, toggles data-open).
223
+ Override --vui-t-panel-y with ~half the panel height for a fuller open. */
224
+ .vui-t-panel {
225
+ transform: translateY(var(--vui-t-panel-y, 16px));
226
+ opacity: 0;
227
+ filter: blur(2px);
228
+ pointer-events: none;
229
+ transition:
230
+ transform 350ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
231
+ opacity 350ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
232
+ filter 350ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
233
+ will-change: transform, opacity, filter;
234
+ }
235
+ .vui-t-panel[data-open="true"] {
236
+ transform: translateY(0);
237
+ opacity: 1;
238
+ filter: blur(0);
239
+ pointer-events: auto;
240
+ transition:
241
+ transform 400ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
242
+ opacity 400ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
243
+ filter 400ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
244
+ }
245
+
246
+ /* PageSlide — side-by-side wizard / tab steps. Pages before the active one
247
+ exit left, pages after exit right (direction set inline per page). */
248
+ .vui-t-pages { position: relative; }
249
+ .vui-t-page {
250
+ position: absolute;
251
+ inset: 0;
252
+ opacity: 0;
253
+ pointer-events: none;
254
+ transform: translateX(var(--vui-t-page-x, 8px));
255
+ filter: blur(3px);
256
+ transition:
257
+ opacity 200ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
258
+ transform 200ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)),
259
+ filter 200ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
260
+ will-change: opacity, transform, filter;
261
+ }
262
+ .vui-t-page.is-active {
263
+ opacity: 1;
264
+ pointer-events: auto;
265
+ transform: translateX(0);
266
+ filter: blur(0);
267
+ }
268
+
269
+ /* IconSwap — cross-fade/scale between two stacked icons (play/pause, moon/sun) */
270
+ .vui-t-icon-swap { position: relative; display: inline-grid; }
271
+ .vui-t-icon-swap .vui-t-icon {
272
+ grid-area: 1 / 1;
273
+ transition:
274
+ opacity 200ms ease-in-out,
275
+ filter 200ms ease-in-out,
276
+ transform 200ms ease-in-out;
277
+ will-change: opacity, filter, transform;
278
+ }
279
+ .vui-t-icon-swap[data-state="a"] .vui-t-icon[data-icon="a"],
280
+ .vui-t-icon-swap[data-state="b"] .vui-t-icon[data-icon="b"] {
281
+ opacity: 1; filter: blur(0); transform: scale(1);
282
+ }
283
+ .vui-t-icon-swap[data-state="a"] .vui-t-icon[data-icon="b"],
284
+ .vui-t-icon-swap[data-state="b"] .vui-t-icon[data-icon="a"] {
285
+ opacity: 0; filter: blur(2px); transform: scale(0.25);
286
+ }
287
+
288
+ /* TextSwap — smoothly replace a label/status string in place.
289
+ --vui-t-text-dur is read by the wrapper to time the text content swap, so
290
+ tune the duration here (one place) and the JS phase stays in sync. */
291
+ .vui-t-text {
292
+ --vui-t-text-dur: 200ms;
293
+ display: inline-block;
294
+ transform: translateY(0);
295
+ filter: blur(0);
296
+ opacity: 1;
297
+ transition:
298
+ transform var(--vui-t-text-dur) ease-out,
299
+ filter var(--vui-t-text-dur) ease-out,
300
+ opacity var(--vui-t-text-dur) ease-out;
301
+ will-change: transform, filter, opacity;
302
+ }
303
+ .vui-t-text.is-exit { transform: translateY(-8px); filter: blur(2px); opacity: 0; }
304
+ .vui-t-text.is-enter-start {
305
+ transform: translateY(8px); filter: blur(2px); opacity: 0; transition: none;
306
+ }
307
+
308
+ /* NotificationBadge — pop a count/dot in and out on a relative trigger */
309
+ @keyframes vui-t-badge-slide-in {
310
+ from { transform: translate(-8.2px, 12.4px); }
311
+ to { transform: translate(0, 0); }
312
+ }
313
+ .vui-t-badge {
314
+ position: absolute;
315
+ top: -6px;
316
+ right: -8px;
317
+ pointer-events: none;
318
+ will-change: transform;
319
+ }
320
+ .vui-t-badge[data-open="true"] {
321
+ animation: vui-t-badge-slide-in 260ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
322
+ }
323
+ .vui-t-badge-dot {
324
+ display: block;
325
+ transform-origin: center;
326
+ transform: scale(1);
327
+ opacity: 1;
328
+ filter: blur(0);
329
+ transition:
330
+ transform 500ms var(--vui-ease-bounce, cubic-bezier(0.34, 1.36, 0.64, 1)),
331
+ opacity 400ms var(--vui-ease-bounce, cubic-bezier(0.34, 1.36, 0.64, 1)),
332
+ filter 500ms var(--vui-ease-bounce, cubic-bezier(0.34, 1.36, 0.64, 1));
333
+ will-change: transform, opacity, filter;
334
+ }
335
+ .vui-t-badge[data-open="false"] .vui-t-badge-dot {
336
+ transform: scale(0);
337
+ opacity: 0;
338
+ filter: blur(2px);
339
+ transition:
340
+ transform 180ms cubic-bezier(0.4, 0, 0.2, 1),
341
+ opacity 180ms cubic-bezier(0.4, 0, 0.2, 1),
342
+ filter 180ms cubic-bezier(0.4, 0, 0.2, 1);
343
+ }
344
+
345
+ /* Expand — height-auto reveal via grid-template-rows 0fr→1fr (no JS measuring,
346
+ no max-height guesswork). The inner wrapper clips overflow while collapsed;
347
+ min-height:0 lets the grid track actually shrink to zero. Content fades in
348
+ slightly behind the height so a tall body doesn't pop. */
349
+ .vui-t-expand {
350
+ display: grid;
351
+ grid-template-rows: 0fr;
352
+ transition: grid-template-rows 320ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
353
+ }
354
+ .vui-t-expand[data-open="true"] { grid-template-rows: 1fr; }
355
+ .vui-t-expand > .vui-t-expand-inner {
356
+ overflow: hidden;
357
+ min-height: 0;
358
+ opacity: 0;
359
+ transition: opacity 180ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
360
+ }
361
+ .vui-t-expand[data-open="true"] > .vui-t-expand-inner {
362
+ opacity: 1;
363
+ transition: opacity 240ms var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1)) 80ms;
364
+ }
365
+
366
+ /* View Transitions — soft default cross-fade for the animateView() helper
367
+ (document.startViewTransition). Slightly slower than the UA default so
368
+ morphs read as intentional rather than a flicker. */
369
+ ::view-transition-old(root),
370
+ ::view-transition-new(root) {
371
+ animation-duration: 260ms;
372
+ animation-timing-function: var(--vui-ease-soft, cubic-bezier(0.22, 1, 0.36, 1));
373
+ }
374
+
375
+ @media (prefers-reduced-motion: reduce) {
376
+ .vui-t-modal, .vui-t-backdrop, .vui-t-menu, .vui-t-panel, .vui-t-page,
377
+ .vui-t-icon-swap .vui-t-icon, .vui-t-text, .vui-t-expand,
378
+ .vui-t-expand > .vui-t-expand-inner {
379
+ transition: none !important;
380
+ }
381
+ .vui-t-badge, .vui-t-badge-dot { animation: none !important; transition: none !important; }
382
+ /* Kill View-Transition animations too — animateView() also short-circuits in
383
+ JS, but a transition started elsewhere still gets neutralized here. */
384
+ ::view-transition-group(*),
385
+ ::view-transition-old(*),
386
+ ::view-transition-new(*) { animation: none !important; }
387
+ }
388
+ `
@@ -0,0 +1,5 @@
1
+ // This file is auto-generated by @omg-dev/vite-plugin. Do not edit manually.
2
+ // To regenerate: restart the dev server or run `vp build`.
3
+
4
+ export const drizzleSchema = {
5
+ }
@@ -0,0 +1 @@
1
+ @import "tailwindcss";
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -0,0 +1,10 @@
1
+ import { StrictMode } from 'react'
2
+ import { createRoot } from 'react-dom/client'
3
+ import './index.css'
4
+ import App from './App.tsx'
5
+
6
+ createRoot(document.getElementById('root')!).render(
7
+ <StrictMode>
8
+ <App />
9
+ </StrictMode>,
10
+ )
@@ -0,0 +1,30 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "es2023",
5
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
6
+ "module": "esnext",
7
+ "types": ["vite/client"],
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "verbatimModuleSyntax": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+ "jsx": "react-jsx",
17
+
18
+ /* Linting */
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "erasableSyntaxOnly": true,
22
+ "noFallthroughCasesInSwitch": true,
23
+
24
+ /* Path alias — keep in lockstep with vite.config.ts */
25
+ "paths": {
26
+ "@/*": ["./src/*"]
27
+ }
28
+ },
29
+ "include": ["src"]
30
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ],
7
+ "compilerOptions": {
8
+ "paths": { "@/*": ["./src/*"] }
9
+ }
10
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "es2023",
5
+ "lib": ["ES2023"],
6
+ "module": "esnext",
7
+ "types": ["node"],
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "verbatimModuleSyntax": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+
17
+ /* Linting */
18
+ "noUnusedLocals": true,
19
+ "noUnusedParameters": true,
20
+ "erasableSyntaxOnly": true,
21
+ "noFallthroughCasesInSwitch": true
22
+ },
23
+ "include": ["vite.config.ts"]
24
+ }
@@ -0,0 +1,23 @@
1
+ import path from 'node:path'
2
+ import { defineConfig } from 'vite-plus'
3
+ import react from '@vitejs/plugin-react'
4
+ import tailwindcss from '@tailwindcss/vite'
5
+ import vibes from '@omg-dev/vite-plugin'
6
+
7
+ export default defineConfig({
8
+ plugins: [react(), tailwindcss(), vibes()],
9
+ resolve: {
10
+ // pi (and humans copying from shadcn docs) reaches for '@/components/...'
11
+ // unconditionally. Bake the alias here so the import resolves in every
12
+ // new project without each one having to configure it.
13
+ alias: { '@': path.resolve(__dirname, './src') },
14
+ },
15
+ server: {
16
+ host: '0.0.0.0',
17
+ allowedHosts: true,
18
+ cors: true,
19
+ hmr: {
20
+ overlay: false,
21
+ },
22
+ },
23
+ })
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "create-omg",
3
+ "version": "0.4.30",
4
+ "description": "Create a new omg.dev app.",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-omg": "./dist/index.mjs"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "bun run scripts/build.ts",
14
+ "test": "bun test",
15
+ "typecheck": "tsc --noEmit"
16
+ },
17
+ "engines": {
18
+ "bun": ">=1.1.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/bun": "^1.0.0",
22
+ "typescript": "npm:@typescript/typescript6@6.0.2"
23
+ },
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/BennyKok/vibes.git"
28
+ },
29
+ "homepage": "https://docs.omg.dev",
30
+ "publishConfig": {
31
+ "access": "public",
32
+ "registry": "https://registry.npmjs.org/"
33
+ },
34
+ "exports": {
35
+ ".": "./dist/index.mjs"
36
+ }
37
+ }