minutework 0.1.31 → 0.1.32
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/EXTERNAL_ALPHA.md +33 -33
- package/README.md +34 -34
- package/assets/claude-local/CLAUDE.md.template +12 -12
- package/assets/claude-local/skills/README.md +1 -1
- package/assets/claude-local/skills/app-pack-authoring/SKILL.md +3 -3
- package/assets/claude-local/skills/capability-gap-reporting/SKILL.md +3 -3
- package/assets/claude-local/skills/generated-workspace-architecture/SKILL.md +2 -2
- package/assets/claude-local/skills/layering-and-import-modes/SKILL.md +2 -2
- package/assets/claude-local/skills/openclaw-skill-importer/SKILL.md +2 -2
- package/assets/claude-local/skills/project-overview-and-strategy/SKILL.md +8 -8
- package/assets/claude-local/skills/published-web-and-mw-core-site/SKILL.md +2 -2
- package/assets/claude-local/skills/standalone-mobile-client/SKILL.md +1 -1
- package/assets/claude-local/skills/vuilder-discovery-output-contract/SKILL.md +6 -6
- package/assets/claude-local/skills/workspace-guidance-refresh/SKILL.md +4 -4
- package/assets/templates/fastapi-sidecar/pyproject.toml +1 -1
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/main.py +1 -1
- package/assets/templates/mobile-app/.env.example +4 -4
- package/assets/templates/mobile-app/AGENTS.md +3 -3
- package/assets/templates/mobile-app/README.md +10 -10
- package/assets/templates/mobile-app/app/(app)/_layout.tsx +2 -2
- package/assets/templates/mobile-app/app/(app)/index.tsx +2 -2
- package/assets/templates/mobile-app/app/(auth)/login.tsx +3 -3
- package/assets/templates/mobile-app/app/_layout.tsx +1 -1
- package/assets/templates/mobile-app/babel.config.js +1 -1
- package/assets/templates/mobile-app/eas.json +1 -1
- package/assets/templates/mobile-app/expo-env.d.ts +1 -1
- package/assets/templates/mobile-app/metro.config.js +2 -2
- package/assets/templates/mobile-app/package.json +1 -1
- package/assets/templates/mobile-app/src/mw/client.ts +3 -3
- package/assets/templates/mobile-app/src/mw/contracts.ts +2 -2
- package/assets/templates/mobile-app/src/mw/endpoints.ts +2 -2
- package/assets/templates/mobile-app/src/mw/env.ts +4 -4
- package/assets/templates/mobile-app/src/mw/session.ts +1 -1
- package/assets/templates/mobile-app/template.json +1 -1
- package/assets/templates/mobile-app/tools/template/validate-template.mjs +2 -2
- package/assets/templates/mobile-app/tsconfig.json +1 -1
- package/assets/templates/next-tenant-app/.env.example +1 -1
- package/assets/templates/next-tenant-app/README.md +3 -3
- package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.test.ts +2 -2
- package/assets/templates/next-tenant-app/src/app/app/page.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/app/app/page.tsx +1 -1
- package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/app/login/page.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/app/login/page.tsx +1 -1
- package/assets/templates/next-tenant-app/src/app/page.test.ts +2 -2
- package/assets/templates/next-tenant-app/src/app/pricing/page.test.ts +2 -2
- package/assets/templates/next-tenant-app/src/lib/content/__fixtures__/public-site-snapshot.ts +14 -14
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.test.ts +3 -3
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.ts +1 -1
- package/assets/templates/next-tenant-app/src/lib/content/empty-state.ts +3 -3
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.test.ts +2 -2
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.ts +1 -1
- package/assets/templates/next-tenant-app/src/lib/public-site.test.ts +1 -1
- package/assets/templates/next-tenant-app/tools/template/with-public-site-fixture.mjs +2 -2
- package/bin/minutework.js +1 -1
- package/dist/agent.js +7 -7
- package/dist/agent.js.map +1 -1
- package/dist/auth.js +7 -7
- package/dist/auth.js.map +1 -1
- package/dist/compile.js +5 -5
- package/dist/config.js +6 -6
- package/dist/config.js.map +1 -1
- package/dist/deploy.js +7 -7
- package/dist/deploy.js.map +1 -1
- package/dist/developer-client.js +2 -2
- package/dist/developer-client.js.map +1 -1
- package/dist/index.js +30 -30
- package/dist/index.js.map +1 -1
- package/dist/init.js +10 -10
- package/dist/init.js.map +1 -1
- package/dist/launcher.js +1 -1
- package/dist/launcher.js.map +1 -1
- package/dist/managed-engine.js +6 -6
- package/dist/managed-engine.js.map +1 -1
- package/dist/orchestrator-context.js +1 -1
- package/dist/orchestrator-context.js.map +1 -1
- package/dist/orchestrator.js +15 -15
- package/dist/orchestrator.js.map +1 -1
- package/dist/paths.js +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/publish.js +3 -3
- package/dist/publish.js.map +1 -1
- package/dist/reporting.js +8 -8
- package/dist/reporting.js.map +1 -1
- package/dist/sandbox.js +5 -5
- package/dist/sandbox.js.map +1 -1
- package/dist/state.js +1 -1
- package/dist/state.js.map +1 -1
- package/dist/tokens.js +9 -9
- package/dist/tokens.js.map +1 -1
- package/dist/workspace-assets.js +6 -6
- package/dist/workspace-assets.js.map +1 -1
- package/dist/workspace.js +3 -3
- package/dist/workspace.js.map +1 -1
- package/package.json +2 -2
- package/vendor/workspace-mcp/context.d.ts +6 -6
- package/vendor/workspace-mcp/context.js +56 -56
- package/vendor/workspace-mcp/context.js.map +1 -1
|
@@ -7,13 +7,13 @@ description: "Exported guidance looks stale, a newly added skill is missing, or
|
|
|
7
7
|
|
|
8
8
|
Use this skill when the generated workspace guidance looks stale, a newly added
|
|
9
9
|
Builder skill is missing from the local workspace, or `CLAUDE.md` / MCP wiring
|
|
10
|
-
does not match the current
|
|
10
|
+
does not match the current MinuteWork CLI export.
|
|
11
11
|
|
|
12
|
-
- From the generated workspace root, run `
|
|
12
|
+
- From the generated workspace root, run `minutework workspace sync-assets`.
|
|
13
13
|
- To preview drift without writing files, run
|
|
14
|
-
`
|
|
14
|
+
`minutework workspace sync-assets --check`.
|
|
15
15
|
- To overwrite conflicting managed files, run
|
|
16
|
-
`
|
|
16
|
+
`minutework workspace sync-assets --force`.
|
|
17
17
|
- This command refreshes the managed guidance surface only:
|
|
18
18
|
- `CLAUDE.md`
|
|
19
19
|
- `skills/**`
|
|
@@ -8,7 +8,7 @@ packages = [{ include = "fastapi_sidecar", from = "src" }]
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "fastapi-sidecar-template"
|
|
10
10
|
version = "0.1.0"
|
|
11
|
-
description = "Canonical FastAPI internal sidecar scaffold for
|
|
11
|
+
description = "Canonical FastAPI internal sidecar scaffold for MinuteWork Builder."
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.12,<4.0"
|
|
14
14
|
dependencies = [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
# DEVELOPER-OWNED — replace freely. Only src/mw/ is MinuteWork substrate.
|
|
2
2
|
#
|
|
3
3
|
# Copy this file to `.env` and set the values for your environment.
|
|
4
4
|
#
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
# the platform issues short-lived bearer tokens at runtime via the native
|
|
9
9
|
# device flow.
|
|
10
10
|
|
|
11
|
-
# Base URL of the
|
|
11
|
+
# Base URL of the MinuteWork platform this app talks to directly.
|
|
12
12
|
# Local dev defaults to http://127.0.0.1:8000 when this is omitted, but physical
|
|
13
13
|
# devices usually need your computer's LAN URL or a tunneled/dev platform URL.
|
|
14
14
|
# The app calls /api/v1/native/... here.
|
|
15
15
|
EXPO_PUBLIC_MW_PLATFORM_BASE_URL=https://<your-platform-base-url>
|
|
16
16
|
|
|
17
|
-
# Optional display name shown in the UI. Defaults to "
|
|
18
|
-
# EXPO_PUBLIC_MW_APP_NAME=
|
|
17
|
+
# Optional display name shown in the UI. Defaults to "MinuteWork".
|
|
18
|
+
# EXPO_PUBLIC_MW_APP_NAME=MinuteWork
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# AGENTS.md — mobile-app starter
|
|
2
2
|
|
|
3
3
|
You are working in a **bring-your-own-UI Expo (React Native + Expo Router)**
|
|
4
|
-
app. **You own all UI/UX.** The only
|
|
4
|
+
app. **You own all UI/UX.** The only MinuteWork-managed code is the thin
|
|
5
5
|
substrate under `src/mw/`.
|
|
6
6
|
|
|
7
7
|
## The one rule
|
|
8
8
|
|
|
9
|
-
**Only `src/mw/` is
|
|
9
|
+
**Only `src/mw/` is MinuteWork substrate.** Build your product in `app/` and your
|
|
10
10
|
own components/modules. Do not move product logic into `src/mw/`, and do not
|
|
11
11
|
build a parallel/local auth stack — the platform owns identity. The mobile app
|
|
12
12
|
is a **direct platform native API client** (bearer token to `/api/v1/native/...`),
|
|
@@ -25,7 +25,7 @@ For the native craft (UI, data, build/release), lean on your local IDE skills:
|
|
|
25
25
|
- `upgrading-expo` — SDK upgrades and dependency fixes
|
|
26
26
|
- `expo-cicd-workflows` — EAS build/deploy pipelines (`.eas/workflows/`)
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## MinuteWork integration shape
|
|
29
29
|
|
|
30
30
|
For how this app fits the platform (the standalone-client exception, the native
|
|
31
31
|
session token, and the device flow), read the Builder skill
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Mobile App Starter (Expo, bring-your-own-UI)
|
|
2
2
|
|
|
3
3
|
A minimal **Expo (React Native + Expo Router)** starter for building a native
|
|
4
|
-
|
|
4
|
+
MinuteWork client. **You own all of the UI/UX.** The only MinuteWork-managed
|
|
5
5
|
code is the thin substrate under `src/mw/`. Everything else in this template is
|
|
6
6
|
a deliberately plain placeholder meant to be replaced.
|
|
7
7
|
|
|
8
|
-
There is **no
|
|
8
|
+
There is **no MinuteWork design system here** — bring your own. Style with
|
|
9
9
|
whatever you like (plain `StyleSheet`, NativeWind/Tailwind, Tamagui, etc.). The
|
|
10
10
|
plain screens use `StyleSheet` only so there is nothing to rip out.
|
|
11
11
|
|
|
@@ -13,17 +13,17 @@ plain screens use `StyleSheet` only so there is nothing to rip out.
|
|
|
13
13
|
|
|
14
14
|
| Path | Owner | Notes |
|
|
15
15
|
| --- | --- | --- |
|
|
16
|
-
| `src/mw/env.ts` | **
|
|
17
|
-
| `src/mw/endpoints.ts` | **
|
|
18
|
-
| `src/mw/contracts.ts` | **
|
|
19
|
-
| `src/mw/client.ts` | **
|
|
20
|
-
| `src/mw/session.ts` | **
|
|
21
|
-
| `tools/template/` | **
|
|
16
|
+
| `src/mw/env.ts` | **MinuteWork substrate** | Validates `EXPO_PUBLIC_MW_PLATFORM_BASE_URL` (+ optional app name) |
|
|
17
|
+
| `src/mw/endpoints.ts` | **MinuteWork substrate** | Builds platform `/api/v1/native/...` URLs |
|
|
18
|
+
| `src/mw/contracts.ts` | **MinuteWork substrate** | Zod schemas for native session + token payloads |
|
|
19
|
+
| `src/mw/client.ts` | **MinuteWork substrate** | Native token client — real browser-assisted PKCE device flow |
|
|
20
|
+
| `src/mw/session.ts` | **MinuteWork substrate** | Secure-store token wrapper (`expo-secure-store`) |
|
|
21
|
+
| `tools/template/` | **MinuteWork substrate** | Template-governance tooling, not shipped app code |
|
|
22
22
|
| `app/**` | **You** | Expo Router screens — replace freely |
|
|
23
23
|
| `package.json`, `app.json`, `eas.json` | **You** | App config — replace freely |
|
|
24
24
|
| `tsconfig.json`, `babel.config.js`, `metro.config.js` | **You** | Tooling config — replace freely |
|
|
25
25
|
|
|
26
|
-
Rule of thumb: **only `src/mw/` is
|
|
26
|
+
Rule of thumb: **only `src/mw/` is MinuteWork substrate.** If you find yourself
|
|
27
27
|
editing `src/mw/` to add product behavior, that behavior probably belongs in
|
|
28
28
|
your own `app/` / components instead.
|
|
29
29
|
|
|
@@ -115,7 +115,7 @@ skill.
|
|
|
115
115
|
|
|
116
116
|
## Distribution
|
|
117
117
|
|
|
118
|
-
**Distribution is your EAS pipeline, not `
|
|
118
|
+
**Distribution is your EAS pipeline, not `minutework deploy`.** This starter is
|
|
119
119
|
not a hosted web/sidecar deployable; it produces native binaries. Build and ship
|
|
120
120
|
with EAS (`eas build`, `eas submit`, EAS Update). `eas.json` ships minimal
|
|
121
121
|
`preview` and `production` profiles to start from. See the `expo-deployment` and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is MinuteWork substrate.
|
|
2
2
|
//
|
|
3
|
-
// Authed area layout. This is where you'd guard on a loaded
|
|
3
|
+
// Authed area layout. This is where you'd guard on a loaded MinuteWork session
|
|
4
4
|
// (via `mwClient.loadSession()`) and redirect to /(auth)/login when there is no
|
|
5
5
|
// valid token. Left as a plain Stack so you can build your own gating/UX.
|
|
6
6
|
import { Stack } from "expo-router";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is MinuteWork substrate.
|
|
2
2
|
//
|
|
3
3
|
// Trivial authed screen. Replace with your real product home. Build your data
|
|
4
4
|
// fetching against the platform native API using the bearer token from
|
|
@@ -21,7 +21,7 @@ export default function HomeScreen() {
|
|
|
21
21
|
<View style={styles.container}>
|
|
22
22
|
<Text style={styles.title}>You are in.</Text>
|
|
23
23
|
<Text style={styles.body}>
|
|
24
|
-
Replace this screen with your product. Only `src/mw/` is
|
|
24
|
+
Replace this screen with your product. Only `src/mw/` is MinuteWork
|
|
25
25
|
substrate — everything else is yours.
|
|
26
26
|
</Text>
|
|
27
27
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is MinuteWork substrate.
|
|
2
2
|
//
|
|
3
3
|
// This screen is intentionally plain and is meant to be REWRITTEN. It exists to
|
|
4
|
-
// show the one integration seam you care about: kicking off
|
|
4
|
+
// show the one integration seam you care about: kicking off MinuteWork's
|
|
5
5
|
// browser-assisted native sign-in through `src/mw/client.ts`.
|
|
6
6
|
//
|
|
7
7
|
// Pressing "Sign in" runs the real device flow: authorize in a system browser ->
|
|
@@ -50,7 +50,7 @@ export default function LoginScreen() {
|
|
|
50
50
|
]}
|
|
51
51
|
>
|
|
52
52
|
<Text style={styles.buttonText}>
|
|
53
|
-
{busy ? "Opening sign in…" : "Sign in with
|
|
53
|
+
{busy ? "Opening sign in…" : "Sign in with MinuteWork"}
|
|
54
54
|
</Text>
|
|
55
55
|
</Pressable>
|
|
56
56
|
</View>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"//": "DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
2
|
+
"//": "DEVELOPER-OWNED — replace freely. Only src/mw/ is MinuteWork substrate. Distribution is YOUR EAS pipeline, not `minutework deploy`.",
|
|
3
3
|
"cli": {
|
|
4
4
|
"version": ">= 12.0.0",
|
|
5
5
|
"appVersionSource": "remote"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="expo/types" />
|
|
2
2
|
|
|
3
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
3
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is MinuteWork substrate.
|
|
4
4
|
// NOTE: This file should not be edited and should be committed; Expo regenerates
|
|
5
5
|
// it. It gives `process.env.EXPO_PUBLIC_*` string typings for `src/mw/env.ts`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is MinuteWork substrate.
|
|
2
2
|
// Keep Metro scoped to this standalone Expo app even when the generated
|
|
3
|
-
//
|
|
3
|
+
// MinuteWork workspace root also has a pnpm workspace for tenant-app.
|
|
4
4
|
const path = require("node:path");
|
|
5
5
|
const { getDefaultConfig } = require("expo/metro-config");
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
//
|
|
1
|
+
// MinuteWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
3
|
+
// MinuteWork native token client. Implements the browser-assisted device flow
|
|
4
4
|
// against the SHIPPED platform native-token endpoints (`/api/v1/native/session/*`).
|
|
5
5
|
//
|
|
6
|
-
// Authentication is owned by the
|
|
6
|
+
// Authentication is owned by the MinuteWork platform. This client only *obtains
|
|
7
7
|
// and uses* a platform-issued bearer token — there is NO JWT minting, NO password
|
|
8
8
|
// handling, NO local user table, and NO parallel auth stack here. Token plaintext
|
|
9
9
|
// is never logged.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
//
|
|
1
|
+
// MinuteWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
|
-
// Zod schemas for the
|
|
3
|
+
// Zod schemas for the MinuteWork platform *native* session payloads. These match
|
|
4
4
|
// the SHIPPED platform native-token slice (`/api/v1/native/session/*`) response
|
|
5
5
|
// shapes exactly (DRF emits snake_case). They describe API responses, not product
|
|
6
6
|
// data. Keep them aligned with the platform serializers in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
//
|
|
1
|
+
// MinuteWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
|
-
// Builds absolute URLs for the
|
|
3
|
+
// Builds absolute URLs for the MinuteWork *platform native* session endpoints.
|
|
4
4
|
//
|
|
5
5
|
// These endpoints are the DIRECT platform API surface for native clients
|
|
6
6
|
// (`/api/v1/native/...`). The mobile app authenticates with a platform-issued
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
//
|
|
1
|
+
// MinuteWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
3
|
// Validates the EXPO_PUBLIC_* configuration the mobile app needs to talk to the
|
|
4
|
-
//
|
|
4
|
+
// MinuteWork platform. Mirrors the spirit of the next-tenant-app
|
|
5
5
|
// `env.server.ts`, but for Expo public env: in Expo, only `EXPO_PUBLIC_*`
|
|
6
6
|
// variables are inlined into the client bundle, and they must be referenced as
|
|
7
7
|
// *static* `process.env.EXPO_PUBLIC_FOO` property accesses so the Expo bundler
|
|
@@ -29,7 +29,7 @@ const optionalNameSchema = z.preprocess((value) => {
|
|
|
29
29
|
}
|
|
30
30
|
const normalized = value.trim();
|
|
31
31
|
return normalized.length > 0 ? normalized : undefined;
|
|
32
|
-
}, z.string().min(1).default("
|
|
32
|
+
}, z.string().min(1).default("MinuteWork"));
|
|
33
33
|
|
|
34
34
|
const envSchema = z.object({
|
|
35
35
|
platformBaseUrl: baseUrlSchema,
|
|
@@ -58,7 +58,7 @@ if (!parsed.success) {
|
|
|
58
58
|
|
|
59
59
|
throw new Error(
|
|
60
60
|
`Invalid Expo public environment for mobile-app: ${issues}. ` +
|
|
61
|
-
"Set EXPO_PUBLIC_MW_PLATFORM_BASE_URL to the
|
|
61
|
+
"Set EXPO_PUBLIC_MW_PLATFORM_BASE_URL to the MinuteWork platform URL.",
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// MinuteWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
3
|
// Secure-store wrapper for the platform-issued native token pair. Persists the
|
|
4
4
|
// `{access, refresh, expiresAt}` triple in the device keychain/keystore via
|
|
@@ -14,5 +14,5 @@
|
|
|
14
14
|
"reference/mwv3-dj6-docs/auth_and_credential_contract.md"
|
|
15
15
|
],
|
|
16
16
|
"deployable": false,
|
|
17
|
-
"notes": "Bring-your-own-UI Expo (React Native + Expo Router) starter. Direct platform native API client (bearer token to /api/v1/native/...), NOT a tenant-app BFF cookie client. Distribution is the developer's EAS pipeline, not `
|
|
17
|
+
"notes": "Bring-your-own-UI Expo (React Native + Expo Router) starter. Direct platform native API client (bearer token to /api/v1/native/...), NOT a tenant-app BFF cookie client. Distribution is the developer's EAS pipeline, not `minutework deploy`. Only src/mw/ is MinuteWork substrate; everything else is developer-owned. src/mw/client.ts implements the real browser-assisted PKCE device flow against the platform native session endpoints; the OAuth-style redirect target is the app.json expo.scheme. This manifest is validated by tools/template/validate-template.mjs, not the strict shared template.schema.json (mobile is not a web/sidecar deployable kind)."
|
|
18
18
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// MinuteWork substrate — template governance tool (not part of the shipped app).
|
|
2
2
|
//
|
|
3
3
|
// Validates this template's `template.json`. The mobile starter is NOT a
|
|
4
4
|
// web/sidecar deployable, so it intentionally does NOT validate against the
|
|
@@ -55,7 +55,7 @@ if (manifest.builder_edit_mode !== "workspace_copy_only") {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (manifest.deployable !== false) {
|
|
58
|
-
throw new Error("mobile-app must declare deployable: false (EAS pipeline, not `
|
|
58
|
+
throw new Error("mobile-app must declare deployable: false (EAS pipeline, not `minutework deploy`)");
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
if (!Array.isArray(manifest.required_bootstrap_steps)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
MW_PLATFORM_BASE_URL=http://127.0.0.1:8000
|
|
2
2
|
MW_PUBLIC_CONTENT_SOURCE=none
|
|
3
3
|
MW_CONTENT_API_TOKEN=
|
|
4
|
-
MW_TEMPLATE_APP_NAME=
|
|
4
|
+
MW_TEMPLATE_APP_NAME=MinuteWork Combined Starter
|
|
5
5
|
MW_PUBLIC_BASE_URL=
|
|
6
6
|
MW_PUBLIC_SITE_PROPERTY_KEY=
|
|
7
7
|
MW_PUBLIC_SITE_ENV=preview
|
|
@@ -59,7 +59,7 @@ Public marketing, docs, and blog routes render through a swappable public-conten
|
|
|
59
59
|
The public content seam lives under `src/lib/content`.
|
|
60
60
|
|
|
61
61
|
The default built-in adapter is `MinuteWorkPublicSiteContentAdapter`. It calls the
|
|
62
|
-
|
|
62
|
+
MinuteWork gateway with a server-only content token and reads the narrow
|
|
63
63
|
`mw.core.site` public-site snapshot contract.
|
|
64
64
|
|
|
65
65
|
`mw.core.site` is treated as a runtime baseline capability. This starter
|
|
@@ -91,13 +91,13 @@ When disabled:
|
|
|
91
91
|
|
|
92
92
|
Copy `.env.example` to `.env.local` when running the template directly. The
|
|
93
93
|
example file uses `MW_PUBLIC_CONTENT_SOURCE=none` so the private `/app` surface
|
|
94
|
-
can boot without
|
|
94
|
+
can boot without MinuteWork CMS credentials; set `MW_PUBLIC_CONTENT_SOURCE` to
|
|
95
95
|
`minutework_cms` and fill the CMS values below when enabling the public site.
|
|
96
96
|
|
|
97
97
|
- `MW_PLATFORM_BASE_URL` is required
|
|
98
98
|
- `MW_PUBLIC_CONTENT_SOURCE` defaults to `none` when omitted; supported values are `minutework_cms`, `custom`, `static_json`, and `none`
|
|
99
99
|
- `MW_CONTENT_API_TOKEN` is required only for `minutework_cms` and must stay server-only
|
|
100
|
-
- `MW_TEMPLATE_APP_NAME` defaults to `
|
|
100
|
+
- `MW_TEMPLATE_APP_NAME` defaults to `MinuteWork Combined Starter`
|
|
101
101
|
- `MW_PUBLIC_BASE_URL` is required for public content sources and should match the deployed public origin; it may be omitted when `MW_PUBLIC_CONTENT_SOURCE=none`
|
|
102
102
|
- `MW_PUBLIC_SITE_PROPERTY_KEY` is required only for `minutework_cms` and selects the `PublishedWebProperty` backing the site
|
|
103
103
|
- `MW_PUBLIC_SITE_ENV` defaults to `preview`
|
|
@@ -25,7 +25,7 @@ vi.mock("@/lib/platform/endpoints.server", () => ({
|
|
|
25
25
|
|
|
26
26
|
vi.mock("@/lib/platform/env.server", () => ({
|
|
27
27
|
env: {
|
|
28
|
-
MW_TEMPLATE_APP_NAME: "
|
|
28
|
+
MW_TEMPLATE_APP_NAME: "MinuteWork Combined Starter",
|
|
29
29
|
MW_ENABLE_RUNTIME_COMMAND_EXAMPLE: false,
|
|
30
30
|
},
|
|
31
31
|
}));
|
|
@@ -47,7 +47,7 @@ describe("runtime commands example page", () => {
|
|
|
47
47
|
it("loads the private shell when the example is enabled", async () => {
|
|
48
48
|
vi.doMock("@/lib/platform/env.server", () => ({
|
|
49
49
|
env: {
|
|
50
|
-
MW_TEMPLATE_APP_NAME: "
|
|
50
|
+
MW_TEMPLATE_APP_NAME: "MinuteWork Combined Starter",
|
|
51
51
|
MW_ENABLE_RUNTIME_COMMAND_EXAMPLE: true,
|
|
52
52
|
},
|
|
53
53
|
}));
|
|
@@ -18,7 +18,7 @@ vi.mock("@/lib/platform/endpoints.server", () => ({
|
|
|
18
18
|
|
|
19
19
|
vi.mock("@/lib/platform/env.server", () => ({
|
|
20
20
|
env: {
|
|
21
|
-
MW_TEMPLATE_APP_NAME: "
|
|
21
|
+
MW_TEMPLATE_APP_NAME: "MinuteWork Combined Starter",
|
|
22
22
|
MW_ENABLE_RUNTIME_COMMAND_EXAMPLE: false,
|
|
23
23
|
},
|
|
24
24
|
}));
|
|
@@ -6,7 +6,7 @@ import { env } from "@/lib/platform/env.server";
|
|
|
6
6
|
export const metadata = {
|
|
7
7
|
title: "Workspace",
|
|
8
8
|
description:
|
|
9
|
-
"Authenticated workspace surface for the combined
|
|
9
|
+
"Authenticated workspace surface for the combined MinuteWork starter.",
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export default async function AppHomePage() {
|
|
@@ -10,7 +10,7 @@ import { readPlatformAuthState } from "@/lib/platform/session.server";
|
|
|
10
10
|
export const metadata = {
|
|
11
11
|
title: "Sign In",
|
|
12
12
|
description:
|
|
13
|
-
"Authenticate into the combined
|
|
13
|
+
"Authenticate into the combined MinuteWork starter to continue into the private workspace surface under /app.",
|
|
14
14
|
robots: {
|
|
15
15
|
index: false,
|
|
16
16
|
follow: false,
|
|
@@ -43,7 +43,7 @@ describe("home page", () => {
|
|
|
43
43
|
|
|
44
44
|
it("renders public home content without auth redirects", async () => {
|
|
45
45
|
getSiteConfig.mockResolvedValue({
|
|
46
|
-
siteName: "
|
|
46
|
+
siteName: "MinuteWork Combined Starter",
|
|
47
47
|
siteDescription: "Combined starter",
|
|
48
48
|
primaryCta: { label: "Sign In", href: "/login" },
|
|
49
49
|
secondaryCta: { label: "Docs", href: "/docs" },
|
|
@@ -61,7 +61,7 @@ describe("home page", () => {
|
|
|
61
61
|
|
|
62
62
|
it("renders the built-in empty home shell when no home page has been published", async () => {
|
|
63
63
|
getSiteConfig.mockResolvedValue({
|
|
64
|
-
siteName: "
|
|
64
|
+
siteName: "MinuteWork Combined Starter",
|
|
65
65
|
siteDescription: "Combined starter",
|
|
66
66
|
primaryCta: { label: "Sign In", href: "/login" },
|
|
67
67
|
secondaryCta: { label: "Docs", href: "/docs" },
|
|
@@ -28,7 +28,7 @@ describe("pricing page", () => {
|
|
|
28
28
|
|
|
29
29
|
it("renders seeded pricing content", async () => {
|
|
30
30
|
getSiteConfig.mockResolvedValue({
|
|
31
|
-
siteName: "
|
|
31
|
+
siteName: "MinuteWork Combined Starter",
|
|
32
32
|
siteDescription: "Combined starter",
|
|
33
33
|
primaryCta: { label: "Sign In", href: "/login" },
|
|
34
34
|
secondaryCta: { label: "Docs", href: "/docs" },
|
|
@@ -45,7 +45,7 @@ describe("pricing page", () => {
|
|
|
45
45
|
|
|
46
46
|
it("renders the built-in empty pricing shell when no pricing page has been published", async () => {
|
|
47
47
|
getSiteConfig.mockResolvedValue({
|
|
48
|
-
siteName: "
|
|
48
|
+
siteName: "MinuteWork Combined Starter",
|
|
49
49
|
siteDescription: "Combined starter",
|
|
50
50
|
primaryCta: { label: "Sign In", href: "/login" },
|
|
51
51
|
secondaryCta: { label: "Docs", href: "/docs" },
|
package/assets/templates/next-tenant-app/src/lib/content/__fixtures__/public-site-snapshot.ts
CHANGED
|
@@ -2,10 +2,10 @@ import type { PublicContentSnapshot } from "@/lib/content/contracts";
|
|
|
2
2
|
|
|
3
3
|
export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
4
4
|
site: {
|
|
5
|
-
siteName: "
|
|
5
|
+
siteName: "MinuteWork Combined Starter",
|
|
6
6
|
siteDescription:
|
|
7
7
|
"SEO-first marketing, docs, blog, and authenticated workspace routes served from one governed Next.js starter.",
|
|
8
|
-
organizationName: "
|
|
8
|
+
organizationName: "MinuteWork",
|
|
9
9
|
footerBlurb:
|
|
10
10
|
"One codebase for public discovery, operator sign-in, and the private Builder-ready workspace shell.",
|
|
11
11
|
primaryCta: {
|
|
@@ -26,7 +26,7 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
26
26
|
docs: {
|
|
27
27
|
eyebrow: "Docs",
|
|
28
28
|
title: "Starter Docs",
|
|
29
|
-
description: "Route public content through the
|
|
29
|
+
description: "Route public content through the MinuteWork public-site snapshot seam.",
|
|
30
30
|
},
|
|
31
31
|
blog: {
|
|
32
32
|
eyebrow: "Blog",
|
|
@@ -40,9 +40,9 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
40
40
|
pageKey: "home",
|
|
41
41
|
path: "/",
|
|
42
42
|
heroEyebrow: "Public Site API",
|
|
43
|
-
heroTitle: "Public routes now read from
|
|
43
|
+
heroTitle: "Public routes now read from MinuteWork content snapshots.",
|
|
44
44
|
heroBody:
|
|
45
|
-
"The tenant-app starter loads public-site content from the
|
|
45
|
+
"The tenant-app starter loads public-site content from the MinuteWork gateway during preview and build, while private routes stay behind the platform-session BFF.",
|
|
46
46
|
primaryCta: {
|
|
47
47
|
label: "Sign In",
|
|
48
48
|
href: "/login",
|
|
@@ -72,7 +72,7 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
72
72
|
},
|
|
73
73
|
],
|
|
74
74
|
seo: {
|
|
75
|
-
title: "
|
|
75
|
+
title: "MinuteWork Combined Starter",
|
|
76
76
|
description:
|
|
77
77
|
"A combined starter with public-site snapshot reads for anonymous routes and a platform-session BFF for private routes.",
|
|
78
78
|
},
|
|
@@ -97,7 +97,7 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
97
97
|
eyebrow: "DX",
|
|
98
98
|
title: "No seeded runtime mode",
|
|
99
99
|
body:
|
|
100
|
-
"The generated starter expects real public-site content from
|
|
100
|
+
"The generated starter expects real public-site content from MinuteWork during development and build.",
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
eyebrow: "Safety",
|
|
@@ -113,9 +113,9 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
113
113
|
},
|
|
114
114
|
],
|
|
115
115
|
seo: {
|
|
116
|
-
title: "
|
|
116
|
+
title: "MinuteWork Combined Starter Pricing",
|
|
117
117
|
description:
|
|
118
|
-
"
|
|
118
|
+
"MinuteWork public-site snapshots let pricing and landing pages stay static-first without local content seeds.",
|
|
119
119
|
},
|
|
120
120
|
},
|
|
121
121
|
],
|
|
@@ -126,12 +126,12 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
126
126
|
eyebrow: "Guide",
|
|
127
127
|
title: "Use the public-site snapshot API",
|
|
128
128
|
description:
|
|
129
|
-
"Configure the tenant-app starter to load preview and live-safe public-site content from
|
|
129
|
+
"Configure the tenant-app starter to load preview and live-safe public-site content from MinuteWork.",
|
|
130
130
|
publishedAt: "2026-03-26T09:00:00.000Z",
|
|
131
131
|
readingTime: "3 min read",
|
|
132
132
|
body: {
|
|
133
133
|
intro:
|
|
134
|
-
"The public-site adapter now talks to the
|
|
134
|
+
"The public-site adapter now talks to the MinuteWork gateway with a server-only content token and unwraps a public-site snapshot envelope.",
|
|
135
135
|
sections: [
|
|
136
136
|
{
|
|
137
137
|
heading: "Environment contract",
|
|
@@ -152,7 +152,7 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
152
152
|
seo: {
|
|
153
153
|
title: "Use the public-site snapshot API",
|
|
154
154
|
description:
|
|
155
|
-
"Configure the
|
|
155
|
+
"Configure the MinuteWork tenant-app starter to fetch public-site snapshots during preview and build.",
|
|
156
156
|
},
|
|
157
157
|
},
|
|
158
158
|
],
|
|
@@ -168,7 +168,7 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
168
168
|
readingTime: "2 min read",
|
|
169
169
|
body: {
|
|
170
170
|
intro:
|
|
171
|
-
"
|
|
171
|
+
"MinuteWork tenant-app starters now fetch public-site content from a gateway API using a dedicated server-only content token.",
|
|
172
172
|
sections: [
|
|
173
173
|
{
|
|
174
174
|
heading: "What changed",
|
|
@@ -182,7 +182,7 @@ export const publicSiteFixtureSnapshot: PublicContentSnapshot = {
|
|
|
182
182
|
seo: {
|
|
183
183
|
title: "Public-site snapshots are now the starter default",
|
|
184
184
|
description:
|
|
185
|
-
"The tenant-app starter now defaults to server-only
|
|
185
|
+
"The tenant-app starter now defaults to server-only MinuteWork public-site content reads during preview and build.",
|
|
186
186
|
},
|
|
187
187
|
},
|
|
188
188
|
],
|
|
@@ -167,7 +167,7 @@ describe("public content adapter", () => {
|
|
|
167
167
|
propertyKey: "main-site",
|
|
168
168
|
});
|
|
169
169
|
|
|
170
|
-
expect(envelope.snapshot.site.siteName).toBe("
|
|
170
|
+
expect(envelope.snapshot.site.siteName).toBe("MinuteWork Combined Starter");
|
|
171
171
|
expect(fetchMock).toHaveBeenCalledWith(
|
|
172
172
|
"https://platform.example.com/api/v1/developer/public-site/snapshots/main-site/?environment=preview",
|
|
173
173
|
expect.objectContaining({
|
|
@@ -232,7 +232,7 @@ describe("public content adapter", () => {
|
|
|
232
232
|
});
|
|
233
233
|
});
|
|
234
234
|
|
|
235
|
-
it("maps
|
|
235
|
+
it("maps MinuteWork public-site snapshots through the adapter interface", async () => {
|
|
236
236
|
const adapter = new MinuteWorkPublicSiteContentAdapter(async () =>
|
|
237
237
|
createEnvelope({
|
|
238
238
|
environment: "live",
|
|
@@ -264,7 +264,7 @@ describe("public content adapter", () => {
|
|
|
264
264
|
await expect(adapter.getMarketingPage("pricing")).resolves.toBeNull();
|
|
265
265
|
});
|
|
266
266
|
|
|
267
|
-
it("loads the default
|
|
267
|
+
it("loads the default MinuteWork public-site path when no custom adapter is provided", async () => {
|
|
268
268
|
const fetchMock = vi.fn().mockResolvedValue(jsonResponse(createEnvelope()));
|
|
269
269
|
vi.stubGlobal("fetch", fetchMock);
|
|
270
270
|
applyServerEnv({});
|