@crossplatformai/skills
Version:
Reusable Agent Skills for CrossPlatform.ai projects.
103 lines (59 loc) • 9.15 kB
Markdown
# Starter-Kit Platform Contract
This is a Post.Build.Ship reference contract, not a standalone skill.
Use this reference when `post`, `build`, or `ship` is already active and the approved task touches cross-platform starter-kit surfaces, SSR/CSR boundaries, shared providers, React Native Web, theme bootstrapping, auth bootstrapping, layout shells, or multi-surface QA.
This contract supplements Post.Build.Ship. It preserves Authorizing User authority, observable
acceptance, platform boundaries, fail-fast approvals, proportionate QA, ownership, and Ship safety.
It adds no mandatory review or presentation fields.
## Public SSR And Private CSR
Public SEO web pages must server-render real body HTML. Marketing pages, docs pages, home pages, public landing pages, and public content pages should have meaningful HTML before hydration. Do not fix public SSR failures by converting those routes, shells, or providers to CSR-only islands.
Private app routes may be CSR or hydration-gated when their first meaningful state depends on browser-only state, client auth validation, local storage, repositories, or client navigation state. Keep those gates scoped to private or app routes instead of leaking them into public SSR shells.
When a route mixes public and private concerns, separate the public SSR shell from browser-only app providers. Prefer a small public route shell plus a scoped private provider boundary over making the entire app root client-only.
When an SSR-safe provider needs a non-blocking render path to keep public HTML visible, expose it as an explicit web-shell opt-in rather than changing the default that every platform inherits.
## Shared Code And Platform Shells
Classify shared React code by every runtime that consumes it. Browser-owned UI rendered only by web
or an Electron renderer is DOM-first even when its data lives in a shared package. Mobile-owned UI
remains React Native. UI shared across browser and native uses a tested platform-selected
implementation or platform-owned renderer/composition seam from
`react-native-web-to-dom.md`.
Shared data and structure do not require one shared rendering primitive. Code in a mobile-facing
barrel must avoid unguarded browser, Electron, Node, DOM, local storage, cookie, `window`,
`document`, native module, or test-harness assumptions. Put browser-only behavior behind an explicit
isolated subpath rather than exporting it through that barrel.
Platform shells and adapters own platform-specific concerns: storage, navigation, runtime config, native/web differences, Electron preload or IPC differences, and automation harness integration. Shared code can depend on explicit adapter interfaces, but it should not reach directly into a platform runtime unless the target repo's architecture already makes that the public boundary.
When fixing CrossPlatform.ai or ThompsonMarkets-style prototype apps, prefer reusable starter-kit primitives, shells, adapters, providers, and tests over one-off app-specific patches. If a fix should apply to both apps, treat that as evidence for extracting or documenting a shared pattern.
## Provider Scope
Browser-only or local-storage-heavy providers should be scoped to the routes that need them. They should not sit in global public SSR shells unless they are SSR-safe and do not block public HTML.
After moving or narrowing a provider, search for every hook or context consumer it serves. Wrap every remaining route, screen, or component subtree that still needs the provider. Do not rely on a smoke test of one route when hook consumers exist elsewhere.
Provider moves should preserve the route access model. Public routes should remain publicly renderable, protected routes should remain protected, and private app routes should not accidentally become public because a provider boundary moved.
## React Native Web SSR CSS
Existing RNW aliases and the server-emitted RNW stylesheet are intentionally retained transitional
infrastructure while an SSR web tree still contains React Native primitives. DOM-first ownership for
browser UI does not authorize removing them from a remaining RNW boundary.
React Native Web first paint in SSR web apps requires server-emitted RNW styles. Web SSR shells should emit the server sheet, commonly from `StyleSheet.getSheet()`, and account for hydration differences with the repository's established hydration-suppression pattern.
CSS layer order should keep RNW and base styles available before hydration while allowing app utilities to win after hydration. A common safe order is:
```css
@layer theme, base, rnw, components, utilities;
```
Use the target repo's existing layer system when it differs, but preserve the same intent: theme/base/RNW styles should exist for first paint, and utilities should remain able to override them.
## Theme Bootstrapping
SSR theme state must be threaded into client theme providers so the first paint and the hydrated UI agree. Public SSR should use a safe fallback such as light or system-safe state, then let the client reconcile after hydration.
Do not require browser-only storage before hydration for public SSR theme decisions. Avoid first-paint contrast bugs, wrong theme icons, and mismatched background colors by passing the server-known initial theme state into the client provider.
Shared theme providers must not make render-while-storage-loads a hidden default. When persisted theme storage is async, default to blocking children until the persisted theme resolves, and treat rendering during storage load as an explicit platform-shell opt-in. This is the safe cross-platform default: blocking only delays first paint, while rendering early can hide a native splash too soon or flash the wrong theme.
Web SSR shells may opt into the non-blocking path because they also thread safe server-seeded initial theme state, so public HTML stays visible before hydration. Native shells that hide their splash on theme readiness should keep the blocking default. Decide this in the platform shell; do not infer it from browser globals, a server-seeded initial-theme prop, or platform detection inside shared UI.
## Auth Bootstrapping
SSR auth hints must be boolean-only unless identity is server-verified. Never serialize decoded unverified JWT claims, user emails, user names, roles, or identity data into public SSR HTML.
Protected routes should remain loading-gated until client validation completes when identity cannot be trusted on the server. Public SSR pages may use a boolean hint to choose shell affordances, but not to expose identity.
If a task needs local or automation auth proof, apply `post-build-ship/references/automation-auth.md` for local/test identity, non-printing code or link rules, sensitive material rules, and Desktop/Electron attach caveats.
## Layout Shells
Layout shells should style empty viewport areas with full-height themed backgrounds. Avoid footer push-down spacer hacks that create unnatural page structure or expose wrong-color blank areas during first paint.
The shell should own the page-level background, min-height behavior, and public/private layout split. Individual pages should not need artificial spacer content just to make the footer sit at the bottom.
## QA And Surface Decisions
For shared layout, auth, theme, provider, RNW, or route-shell changes, make an explicit validation decision for every existing surface the change can affect: `apps/web`, `apps/mobile`, and `apps/desktop` when those surfaces exist.
Use the normal Post.Build.Ship QA contract for exact commands. For every changed runnable package or app with `test:unit`, run the scoped unit-test command unless the approved handoff records a user-approved exclusion. For changed client surfaces with `test:e2e` or matching root e2e scripts, run or explicitly exclude the relevant automated e2e command according to the existing QA rules.
If the target repo has no matching script or surface, record that as unavailable. Do not run package scripts from the workspace root just to satisfy this contract.
## Evidence Examples
These examples are evidence for the contract, not generic required paths:
1. CrossPlatform.ai commit `472e1c442 fix(web): stabilize public SSR boot` showed that public SSR can be preserved by scoping browser-heavy providers, emitting RNW CSS, threading safe theme state, and avoiding unverified identity serialization.
2. ThompsonMarkets commit `a89a9f6 fix(web): stabilize shell first paint` showed the same starter-kit concerns in another proof app: stable first paint, themed shell backgrounds, provider scoping, and reusable shared fixes beat one-off prototype patches.
3. CrossPlatform.ai commit `59a47560b fix(ui): gate async theme loading` corrected `472e1c442` by gating render-while-storage-load behind an explicit provider opt-in, after the always-render default regressed native splash timing and caused theme flash. Web opts in; mobile and desktop keep the blocking default.
Do not copy app-specific routes, file paths, storage keys, provider names, or port numbers into generic skill guidance unless they are clearly labeled as examples for that target repo.