create-gentiq-app 0.14.0 β†’ 0.15.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,7 +32,7 @@ pnpm create gentiq-app my-awesome-ai
32
32
  - ⚑ **AI Streaming**: Real-time agent responses via PydanticAI and Vercel AI SDK.
33
33
  - πŸ› οΈ **Admin Dashboard**: Built-in analytics, history logs, and user management.
34
34
  - πŸ’° **Atomic Balance**: Native tracking and enforcement of per-user token and request limits.
35
- - πŸ“‚ **Flexible Persistence**: Integrated MinIO/S3 for file storage and MongoDB for state.
35
+ - πŸ“‚ **Flexible Persistence**: SQLite + local filesystem out of the box; MongoDB + MinIO/S3 for production.
36
36
  - πŸ”’ **Enterprise-Grade Security**: Full JWT authentication suite and encrypted sessions.
37
37
 
38
38
  ---
@@ -45,11 +45,12 @@ When you initialize a new app, the CLI generates a modern, monorepo-friendly str
45
45
  my-awesome-ai/
46
46
  β”œβ”€β”€ backend/ # FastAPI + PydanticAI application
47
47
  β”‚ β”œβ”€β”€ main.py # App entry point
48
- β”‚ └── pyproject.toml # Python dependencies (UV managed)
48
+ β”‚ β”œβ”€β”€ pyproject.toml # Python dependencies (UV managed)
49
+ β”‚ β”œβ”€β”€ .env.example # Environment variable template
50
+ β”‚ └── .env # Generated, with real secrets β€” gitignored
49
51
  β”œβ”€β”€ frontend/ # Vite + React application
50
52
  β”‚ β”œβ”€β”€ src/ # UI components and hooks
51
53
  β”‚ └── package.json # Frontend dependencies
52
- β”œβ”€β”€ .env.example # Environment variable template
53
54
  └── README.md # Your project documentation
54
55
  ```
55
56
 
@@ -59,24 +60,27 @@ my-awesome-ai/
59
60
 
60
61
  Once your project is scaffolded, follow these steps to get running:
61
62
 
62
- ### 1. Environment Setup
63
- Copy the example environment file and add your API keys and modify other variables as desired:
64
- ```bash
65
- cp .env.example .env
66
- ```
63
+ The CLI does the setup for you: it installs the backend dependencies with `uv sync`,
64
+ installs the frontend dependencies with your package manager, and writes `backend/.env`
65
+ with freshly generated `JWT_SECRET_KEY` and `BACKEND_API_KEY` values. So once it
66
+ finishes, the project runs.
67
+
68
+ ### 1. Launch Backend
67
69
 
68
- ### 2. Launch Backend
69
- The backend uses `uv` for lightning-fast Python package management.
70
70
  ```bash
71
71
  cd backend
72
- uv sync
73
72
  uv run uvicorn main:app.api --reload --port 8000
74
73
  ```
75
74
 
76
- ### 3. Launch Frontend
75
+ The only value you have to supply yourself is the AI provider key. If you did not paste
76
+ one at the prompt, set `OPENAI_API_KEY` in `backend/.env` before starting β€” the agent
77
+ definition in `main.py` builds its provider client on import, so an absent key is a
78
+ startup error rather than a failed chat. Using a different provider? Change the model
79
+ string in `backend/main.py` and set that provider's key instead.
80
+
81
+ ### 2. Launch Frontend
77
82
  ```bash
78
83
  cd frontend
79
- npm install
80
84
  npm run dev
81
85
  ```
82
86
 
@@ -84,6 +88,143 @@ Your app is now live at `http://localhost:5173`!
84
88
 
85
89
  ---
86
90
 
91
+ ## Options
92
+
93
+ ```bash
94
+ npx create-gentiq-app@latest [directory] [options]
95
+ ```
96
+
97
+ | Flag | Effect |
98
+ | --- | --- |
99
+ | `--pm <name>` | Package manager for the frontend install: `pnpm`, `npm`, `yarn` or `bun`. Defaults to the one that invoked the CLI. |
100
+ | `--no-install` | Scaffold only β€” skip `uv sync` and the frontend install. |
101
+ | `--openai-key <key>` | Write this `OPENAI_API_KEY` into `backend/.env` instead of prompting. |
102
+ | `-y`, `--yes` | Accept every default and never prompt. Also the automatic behaviour when there is no TTY, so the CLI is usable from CI. |
103
+ | `-h`, `--help` | Show usage. |
104
+
105
+ Missing tools are reported, not fatal: without `uv` the backend install is skipped with
106
+ an install link, and a package manager that is not on `PATH` falls back to one that is.
107
+ The scaffold itself is complete either way, and the printed next steps name whatever is
108
+ left to run by hand.
109
+
110
+ ---
111
+
112
+ ## Using Tailwind in a Gentiq app
113
+
114
+ The scaffold ships **no Tailwind** β€” `gentiq/style.css` is already compiled, and the chat
115
+ and admin UIs are fully styled by it. You only need Tailwind if you are writing your own
116
+ components (a custom tool card, say). If you add it, read this section first: two Tailwind
117
+ builds in one document need one extra line to coexist, and without it they break each
118
+ other silently.
119
+
120
+ ### Why it needs care
121
+
122
+ Tailwind guarantees that a variant (`md:`, `hover:`) is emitted *after* the plain utility
123
+ it is meant to override β€” that is the whole reason `flex-col md:flex-row` works. The
124
+ guarantee holds **per build**. Gentiq ships precompiled CSS, so adding Tailwind to your app
125
+ creates a second, independently sorted set of utilities, and concatenating them destroys
126
+ the ordering: whichever set lands later wins every tie, regardless of which stylesheet
127
+ "owns" the class.
128
+
129
+ Both directions are broken, and neither announces itself:
130
+
131
+ | Your utilities last | Gentiq's utilities last |
132
+ | --- | --- |
133
+ | Your `.flex-col` beats gentiq's `.md:flex-row` β€” the admin header collapses into a vertical stack at every width | Gentiq's `.grid-cols-2` beats your `.sm:grid-cols-3` β€” your own grids stop responding |
134
+
135
+ Reordering does not fix it, because the problem is not the order. It is that there are two
136
+ sorts. The fix is to collapse them back to one.
137
+
138
+ ### The setup
139
+
140
+ Put this at the top of `src/index.css`, and delete `import 'gentiq/style.css'` from
141
+ `src/App.tsx` (this file has to load first, so it must own that import):
142
+
143
+ ```css
144
+ /* Layer order for the document: gentiq's layers first, yours last. */
145
+ @layer properties, gentiq-theme, gentiq-base, gentiq-components, gentiq-utilities,
146
+ theme, base, components, utilities;
147
+
148
+ @import 'gentiq/style.css';
149
+
150
+ /* Theme + utilities only β€” NOT `@import 'tailwindcss'`. That bundles preflight,
151
+ and gentiq's stylesheet already ships one; a second copy lands after gentiq's
152
+ rules and its `border: 0 solid` resets border-color to currentColor, which
153
+ paints every unstyled border in the app the foreground colour. */
154
+ @import 'tailwindcss/theme.css' layer(theme);
155
+ @import 'tailwindcss/utilities.css' layer(utilities);
156
+
157
+ /* The line that actually makes the two coexist: scan gentiq's bundles so YOUR
158
+ build emits gentiq's classes too. One build, one sort, every variant back
159
+ after its base utility. Gentiq's precompiled layer is then shadowed for every
160
+ class you regenerate, and still supplies its custom `@utility` rules (`glass`,
161
+ the loader animations), whose names contend with nothing you emit. */
162
+ @source '../node_modules/gentiq/dist/gentiq-index.es.js';
163
+ @source '../node_modules/gentiq/dist/gentiq-admin.es.js';
164
+
165
+ /* Gentiq's design tokens, registered with YOUR Tailwind instance. Gentiq declares
166
+ the same map in its own `@theme inline`, but that lives in its compiled
167
+ stylesheet, which your compiler never sees β€” so without this block utilities
168
+ like `hover:border-primary/40` silently generate nothing. `inline` is what makes
169
+ them resolve at runtime, so ThemeProvider can keep rewriting accent and theme. */
170
+ @theme inline {
171
+ --color-background: var(--background);
172
+ --color-foreground: var(--foreground);
173
+ --color-card: var(--card);
174
+ --color-card-foreground: var(--card-foreground);
175
+ --color-popover: var(--popover);
176
+ --color-popover-foreground: var(--popover-foreground);
177
+ --color-primary: var(--primary);
178
+ --color-primary-foreground: var(--primary-foreground);
179
+ --color-secondary: var(--secondary);
180
+ --color-secondary-foreground: var(--secondary-foreground);
181
+ --color-muted: var(--muted);
182
+ --color-muted-foreground: var(--muted-foreground);
183
+ --color-accent: var(--accent);
184
+ --color-accent-foreground: var(--accent-foreground);
185
+ --color-destructive: var(--destructive);
186
+ --color-border: var(--border);
187
+ --color-input: var(--input);
188
+ --color-ring: var(--ring);
189
+
190
+ --radius-sm: calc(var(--radius) - 4px);
191
+ --radius-md: calc(var(--radius) - 2px);
192
+ --radius-lg: var(--radius);
193
+ --radius-xl: calc(var(--radius) + 4px);
194
+ }
195
+ ```
196
+
197
+ Do not set `body { font-family: … !important }` here. `ThemeProvider` composes the
198
+ configured face with `var(--font-script)` and writes it inline to `<html>` and `<body>`;
199
+ an `!important` rule beats that inline style and strips the per-script fallback, leaving
200
+ Persian and Arabic text in a serif default.
201
+
202
+ The `@source` lines cost roughly 10–13 kB gzipped, because your build re-emits the
203
+ utilities gentiq already shipped. That is the price of a correct cascade; the duplicate
204
+ rules are identical and fully shadowed.
205
+
206
+ ### Layers
207
+
208
+ Gentiq publishes into `gentiq-theme`, `gentiq-base`, `gentiq-components` and
209
+ `gentiq-utilities` rather than the bare `theme` / `base` / `components` / `utilities`
210
+ (versions up to and including `0.15.0-beta.1` used the bare names). Those generic names belong to your document, and gentiq
211
+ claiming them is what let the two builds merge by accident in the first place. Gentiq
212
+ deliberately does **not** pre-register your layer names, so your stylesheet keeps the
213
+ position it has always had; the `@layer` statement above is where you decide the order.
214
+
215
+ The setup above works against older versions too β€” the `gentiq-*` layers just stay empty
216
+ and gentiq's stylesheet lands in `theme` / `base` / `utilities` instead, still ahead of
217
+ your regenerated superset.
218
+
219
+ ### Checking it
220
+
221
+ The admin dashboard header is the fastest canary β€” it is the layout in the product that
222
+ leans hardest on `md:` overrides. Open `/admin` above 768px: the logo and the navigation
223
+ tabs sit on one row. If they are stacked vertically, your utilities are beating gentiq's
224
+ variants and `@source` is missing or pointing at the wrong path.
225
+
226
+ ---
227
+
87
228
  ## Why Gentiq?
88
229
 
89
230
  Unlike generic boilerplates, Gentiq is built with **developer velocity** and **production scalability** in mind. It provides the "boring" parts of AI developmentβ€”authentication, rate limiting, and persistenceβ€”so you can focus on building your agents.
package/copy-template.js CHANGED
@@ -2,6 +2,8 @@ import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
 
5
+ import { shouldSkipEntry } from './skipped-entries.js';
6
+
5
7
  const __filename = fileURLToPath(import.meta.url);
6
8
  const __dirname = path.dirname(__filename);
7
9
 
@@ -15,10 +17,7 @@ async function copyTemplate() {
15
17
  await fs.emptyDir(dest);
16
18
 
17
19
  await fs.copy(src, dest, {
18
- filter: (src) => {
19
- const basename = path.basename(src);
20
- return !['node_modules', '.venv', '__pycache__', '.ruff_cache', 'dist', '.storage', 'gentiq.db', 'uv.lock', 'package-lock.json', 'pnpm-lock.yaml'].includes(basename);
21
- }
20
+ filter: (src) => !shouldSkipEntry(path.basename(src)),
22
21
  });
23
22
 
24
23
  console.log('Template copied successfully!');