uniquick 0.1.0 → 0.1.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
@@ -5,11 +5,11 @@ dashboards, live multiplayer pages, AI tools) to the University of Illinois
5
5
  UniQuick platform. Visitors sign in silently with their `@illinois.edu` account;
6
6
  data, file storage, realtime, and AI are provided by the platform.
7
7
 
8
- Live at **https://uniquick.azurewebsites.net**.
8
+ Live at **https://quick.disruptionlab.illinois.edu**.
9
9
 
10
10
  ## 1. Get a deploy token (once)
11
11
 
12
- Open **https://uniquick.azurewebsites.net/token**, sign in with your
12
+ Open **https://quick.disruptionlab.illinois.edu/token**, sign in with your
13
13
  `@illinois.edu` account, create a token, and copy it (shown once, looks like
14
14
  `qk_...`). Treat it like a password; revoke it from the same page any time.
15
15
 
@@ -43,14 +43,14 @@ npx -y uniquick delete <slug> --yes
43
43
 
44
44
  Site names are auto-prefixed with your netid (`my-site` → `netid-my-site`); the
45
45
  create output shows the final id. Your site is served at
46
- `https://uniquick.azurewebsites.net/s/<slug>/`.
46
+ `https://quick.disruptionlab.illinois.edu/s/<slug>/`.
47
47
 
48
48
  ## Building a site
49
49
 
50
50
  Make a folder with an `index.html` that loads the SDK:
51
51
 
52
52
  ```html
53
- <script src="https://uniquick.azurewebsites.net/sdk.js"></script>
53
+ <script src="https://quick.disruptionlab.illinois.edu/sdk.js"></script>
54
54
  <script type="module">
55
55
  await quick.ready; // silent SSO done
56
56
  quick.user; // { name, upn }
@@ -62,14 +62,14 @@ Make a folder with an `index.html` that loads the SDK:
62
62
  ```
63
63
 
64
64
  Full SDK reference (written for coding agents): paste
65
- **https://uniquick.azurewebsites.net/llms.txt** into your agent's context.
65
+ **https://quick.disruptionlab.illinois.edu/llms.txt** into your agent's context.
66
66
 
67
67
  ## Configuration
68
68
 
69
69
  | Env | Default | Purpose |
70
70
  |-----|---------|---------|
71
71
  | `UNIQUICK_TOKEN` | — | Deploy token from `/token` (required) |
72
- | `UNIQUICK_URL` | `https://uniquick.azurewebsites.net` | Platform base URL |
72
+ | `UNIQUICK_URL` | `https://quick.disruptionlab.illinois.edu` | Platform base URL |
73
73
  | `UNIQUICK_DEPLOY_ROOT` | cwd | Directories the MCP `deploy_site` tool may read from |
74
74
 
75
75
  Questions → vishal@illinois.edu.
package/dist/cli.js CHANGED
@@ -75,16 +75,6 @@ function buildManifest(dir, options = {}) {
75
75
  walk(dir);
76
76
  return { files };
77
77
  }
78
- function checkDeployRoot(dir, root) {
79
- const realRoot = realpathSync(resolve(root));
80
- const realDir = realpathSync(resolve(dir));
81
- if (realDir !== realRoot && !realDir.startsWith(realRoot + sep)) {
82
- throw new Error(
83
- `refusing to deploy '${dir}': it is outside the deploy root '${realRoot}'. Set UNIQUICK_DEPLOY_ROOT to a parent directory of your site files to allow it.`
84
- );
85
- }
86
- return realDir;
87
- }
88
78
  function parseArgs(argv) {
89
79
  const [command = "", ...rest] = argv;
90
80
  const positional = [];
@@ -106,7 +96,7 @@ function parseArgs(argv) {
106
96
  }
107
97
  return { command, positional, flags };
108
98
  }
109
- var BASE = (process.env.UNIQUICK_URL ?? "https://uniquick.azurewebsites.net").replace(/\/+$/, "");
99
+ var BASE = (process.env.UNIQUICK_URL ?? "https://quick.disruptionlab.illinois.edu").replace(/\/+$/, "");
110
100
  function fail(msg) {
111
101
  console.error(`error: ${msg}`);
112
102
  process.exit(1);
@@ -156,13 +146,14 @@ usage:
156
146
  uniquick create <slug> --title <title> [--data-mode open|owner-write]
157
147
  uniquick deploy <dir> --site <slug>
158
148
  uniquick list
149
+ uniquick share <slug> [--description <text>] [--unshare]
159
150
  uniquick delete <slug> --yes
160
151
  uniquick token-check
161
152
 
162
153
  (from a repo checkout, prefix any command with: npx tsx cli/uniquick.ts)
163
154
 
164
155
  env:
165
- UNIQUICK_URL platform base URL (default https://uniquick.azurewebsites.net)
156
+ UNIQUICK_URL platform base URL (default https://quick.disruptionlab.illinois.edu)
166
157
  UNIQUICK_TOKEN deploy token from ${BASE}/token`;
167
158
  async function main() {
168
159
  const { command, positional, flags } = parseArgs(process.argv.slice(2));
@@ -190,8 +181,28 @@ async function main() {
190
181
  if (!manifest.files.some((f) => f.path === "index.html")) {
191
182
  console.error(`warning: no top-level index.html \u2014 ${BASE}/s/${site}/ will 404`);
192
183
  }
193
- await api("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
184
+ const res = await api("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
194
185
  console.log(`Deployed ${manifest.files.length} file(s) -> ${BASE}/s/${site}/`);
186
+ if (res && res.gallery === false) {
187
+ console.log(
188
+ `
189
+ Want others at Illinois to discover it? Add it to the gallery:
190
+ npx -y uniquick share ${site} --description "one line about it"`
191
+ );
192
+ }
193
+ break;
194
+ }
195
+ case "share": {
196
+ const slug = positional[0] ?? fail("usage: uniquick share <slug> [--description <text>] [--unshare]");
197
+ const unshare = flags.unshare === true;
198
+ const body = { gallery: !unshare };
199
+ if (typeof flags.description === "string") body.gallery_description = flags.description;
200
+ await api("PATCH", `/api/sites/${encodeURIComponent(slug)}`, body);
201
+ if (unshare) {
202
+ console.log(`Removed '${slug}' from the public gallery.`);
203
+ } else {
204
+ console.log(`Shared '${slug}' to the public gallery -> ${BASE}/gallery`);
205
+ }
195
206
  break;
196
207
  }
197
208
  case "list": {
@@ -231,11 +242,10 @@ var isMain = !!process.argv[1] && import.meta.url === pathToFileURL(resolve(proc
231
242
  if (isMain) {
232
243
  main().catch((e) => fail(e?.message ?? String(e)));
233
244
  }
234
- export {
235
- MAX_FILE_BYTES,
236
- MAX_TOTAL_BYTES,
237
- buildManifest,
238
- checkDeployRoot,
239
- mimeFor,
240
- parseArgs
241
- };
245
+
246
+ // entries/cli.ts
247
+ main().catch((e) => {
248
+ const msg = e instanceof Error ? e.message : String(e);
249
+ console.error(`error: ${msg}`);
250
+ process.exit(1);
251
+ });
package/dist/mcp.js CHANGED
@@ -113,7 +113,7 @@ function parseArgs(argv) {
113
113
  }
114
114
  return { command, positional, flags };
115
115
  }
116
- var BASE = (process.env.UNIQUICK_URL ?? "https://uniquick.azurewebsites.net").replace(/\/+$/, "");
116
+ var BASE = (process.env.UNIQUICK_URL ?? "https://quick.disruptionlab.illinois.edu").replace(/\/+$/, "");
117
117
  function fail(msg) {
118
118
  console.error(`error: ${msg}`);
119
119
  process.exit(1);
@@ -163,13 +163,14 @@ usage:
163
163
  uniquick create <slug> --title <title> [--data-mode open|owner-write]
164
164
  uniquick deploy <dir> --site <slug>
165
165
  uniquick list
166
+ uniquick share <slug> [--description <text>] [--unshare]
166
167
  uniquick delete <slug> --yes
167
168
  uniquick token-check
168
169
 
169
170
  (from a repo checkout, prefix any command with: npx tsx cli/uniquick.ts)
170
171
 
171
172
  env:
172
- UNIQUICK_URL platform base URL (default https://uniquick.azurewebsites.net)
173
+ UNIQUICK_URL platform base URL (default https://quick.disruptionlab.illinois.edu)
173
174
  UNIQUICK_TOKEN deploy token from ${BASE}/token`;
174
175
  async function main() {
175
176
  const { command, positional, flags } = parseArgs(process.argv.slice(2));
@@ -197,8 +198,28 @@ async function main() {
197
198
  if (!manifest.files.some((f) => f.path === "index.html")) {
198
199
  console.error(`warning: no top-level index.html \u2014 ${BASE}/s/${site}/ will 404`);
199
200
  }
200
- await api("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
201
+ const res = await api("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
201
202
  console.log(`Deployed ${manifest.files.length} file(s) -> ${BASE}/s/${site}/`);
203
+ if (res && res.gallery === false) {
204
+ console.log(
205
+ `
206
+ Want others at Illinois to discover it? Add it to the gallery:
207
+ npx -y uniquick share ${site} --description "one line about it"`
208
+ );
209
+ }
210
+ break;
211
+ }
212
+ case "share": {
213
+ const slug = positional[0] ?? fail("usage: uniquick share <slug> [--description <text>] [--unshare]");
214
+ const unshare = flags.unshare === true;
215
+ const body = { gallery: !unshare };
216
+ if (typeof flags.description === "string") body.gallery_description = flags.description;
217
+ await api("PATCH", `/api/sites/${encodeURIComponent(slug)}`, body);
218
+ if (unshare) {
219
+ console.log(`Removed '${slug}' from the public gallery.`);
220
+ } else {
221
+ console.log(`Shared '${slug}' to the public gallery -> ${BASE}/gallery`);
222
+ }
202
223
  break;
203
224
  }
204
225
  case "list": {
@@ -240,7 +261,7 @@ if (isMain) {
240
261
  }
241
262
 
242
263
  // ../mcp/server.ts
243
- var BASE2 = (process.env.UNIQUICK_URL ?? "https://uniquick.azurewebsites.net").replace(/\/+$/, "");
264
+ var BASE2 = (process.env.UNIQUICK_URL ?? "https://quick.disruptionlab.illinois.edu").replace(/\/+$/, "");
244
265
  var TOKEN = process.env.UNIQUICK_TOKEN ?? "";
245
266
  var DEPLOY_ROOT = resolve2(process.env.UNIQUICK_DEPLOY_ROOT ?? process.cwd());
246
267
  var slugSchema = z.string().regex(/^[a-z0-9][a-z0-9-]{1,62}$/, "slug must match ^[a-z0-9][a-z0-9-]{1,62}$");
@@ -307,8 +328,38 @@ server.registerTool(
307
328
  const manifest = buildManifest(real);
308
329
  if (manifest.files.length === 0) throw new Error(`no files found in ${real}`);
309
330
  const warn = manifest.files.some((f) => f.path === "index.html") ? "" : "\nWarning: no top-level index.html \u2014 the site root will 404.";
310
- await api2("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
311
- return ok(`Deployed ${manifest.files.length} file(s) to ${BASE2}/s/${site}/${warn}`);
331
+ const result = await api2("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
332
+ const nudge = result && result.gallery === false ? `
333
+
334
+ Now that it's live, ask the user if they'd like to share this app on the public UniQuick gallery (${BASE2}/gallery) so others at Illinois can discover it. If they say yes, call share_to_gallery with a one-line description.` : "";
335
+ return ok(`Deployed ${manifest.files.length} file(s) to ${BASE2}/s/${site}/${warn}${nudge}`);
336
+ }
337
+ );
338
+ server.registerTool(
339
+ "share_to_gallery",
340
+ {
341
+ description: `Add a site to the public UniQuick gallery (${BASE2}/gallery) so anyone at Illinois can discover it. ALWAYS ask the user before calling this \u2014 the app is then listed publicly with the owner's name and a description. Provide a short one-line description of what the app does.`,
342
+ inputSchema: {
343
+ site: slugSchema.describe("Site slug to share"),
344
+ description: z.string().max(280).optional().describe("One-line description shown on the gallery card")
345
+ }
346
+ },
347
+ async ({ site, description }) => {
348
+ const body = { gallery: true };
349
+ if (description) body.gallery_description = description;
350
+ await api2("PATCH", `/api/sites/${encodeURIComponent(site)}`, body);
351
+ return ok(`Shared '${site}' to the public gallery -> ${BASE2}/gallery`);
352
+ }
353
+ );
354
+ server.registerTool(
355
+ "unshare_from_gallery",
356
+ {
357
+ description: "Remove a site from the public UniQuick gallery. It stays live at its /s/<slug>/ URL.",
358
+ inputSchema: { site: slugSchema.describe("Site slug to remove from the gallery") }
359
+ },
360
+ async ({ site }) => {
361
+ await api2("PATCH", `/api/sites/${encodeURIComponent(site)}`, { gallery: false });
362
+ return ok(`Removed '${site}' from the public gallery.`);
312
363
  }
313
364
  );
314
365
  server.registerTool(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniquick",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "CLI + MCP server for UniQuick — deploy AI-built sites to the UIUC UniQuick platform with one prompt.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -39,5 +39,5 @@
39
39
  "url": "https://github.com/gies-ai-experiments/uniquick.git",
40
40
  "directory": "npm"
41
41
  },
42
- "homepage": "https://uniquick.azurewebsites.net"
42
+ "homepage": "https://quick.disruptionlab.illinois.edu"
43
43
  }