https://github.com/ankhorage/templates
App templates and manifest generators for Ankhorage — ZORA-based project scaffolds built on @ankhorage/surface.
https://github.com/ankhorage/templates
ankhorage app-template code-generator cross-platform design-system design-tokens expo project-template react-native react-native-web scaffolding templates typescript ui-kit zora
Last synced: 16 days ago
JSON representation
App templates and manifest generators for Ankhorage — ZORA-based project scaffolds built on @ankhorage/surface.
- Host: GitHub
- URL: https://github.com/ankhorage/templates
- Owner: ankhorage
- License: mit
- Created: 2026-04-19T09:03:39.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-02T03:34:51.000Z (19 days ago)
- Last Synced: 2026-06-02T04:16:46.932Z (19 days ago)
- Topics: ankhorage, app-template, code-generator, cross-platform, design-system, design-tokens, expo, project-template, react-native, react-native-web, scaffolding, templates, typescript, ui-kit, zora
- Language: TypeScript
- Homepage: https://ankhorage.com
- Size: 492 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# @ankhorage/templates
Reusable Ankhorage app templates, presets, and manifest generators.
## Usage
```ts
import {
createCategoryAppManifest,
createStarterTemplate,
listStarterTemplatesByCategory,
} from '@ankhorage/templates';
const manifest = createCategoryAppManifest('social_community');
const creatorManifest = createStarterTemplate(seed, {
templateId: 'creator',
});
const gameTemplates = listStarterTemplatesByCategory('games');
```
## Category Starter Templates
Starter templates are category-aware. A category can expose one or more template variants.
For example, `social_community` provides a default community starter and a `creator`
starter, while `games` provides the default quest-loop starter and a `chess` starter.
Use `listStarterTemplatesByCategory(category)` when an editor or generator needs a selectable
list for one category. It returns summaries only, not factories:
```ts
const templates = listStarterTemplatesByCategory('games');
// [
// { id: 'default', category: 'games', label: 'Quest loop', ... },
// { id: 'chess', category: 'games', label: 'Chess', ... },
// ]
```
Use `listStarterTemplateSummaries()` when a tool needs all registered starter choices.
Default resolution is deterministic:
- no `templateId` selects `default`
- an unknown template id falls back to that category's `default`
- an unregistered category falls back to `fallback/default`
The generated manifest includes category-specific routes, screens, copy, and route icons.
Icons use the existing route `icon: IconSpec` property from `@ankhorage/contracts`:
```ts
{
name: 'groups',
screenId: 'social_community-community-starter-groups',
label: 'Groups',
icon: { provider: 'material-community', name: 'account-group-outline' },
}
```
Auth behavior is not modeled as a visible navigation route in category templates. It remains
controlled by the manifest `infra` and `settings.authFlow` configuration. The original generic
starter remains available as the fallback template and preserves its existing sign-in screen.
## Current Templates
All `AppCategory` values have a dedicated `starter/default` template with an explicit
`navigator.type`, deterministic route labels, and `material-community` route icons.
| Category | Navigator | Routes (labels) | Icons (`material-community`) |
| ----------------------- | --------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `books_reading` | `tabs` | Library · Discover · Lists · Notes · Profile | `bookshelf` · `compass-outline` · `format-list-checks` · `notebook-outline` · `account-circle-outline` |
| `business_productivity` | `drawer` | Dashboard · Projects · Tasks · Calendar · Reports · Settings | `view-dashboard-outline` · `folder-multiple-outline` · `clipboard-check-outline` · `calendar-month-outline` · `chart-box-outline` · `cog-outline` |
| `developer_tools` | `drawer` | Dashboard · Builds · Incidents · Environments · Deployments · Settings | `view-dashboard-outline` · `hammer-wrench` · `alert-circle-outline` · `server-network` · `rocket-launch-outline` · `cog-outline` |
| `education_learning` | `tabs` | Courses · Study · Practice · Progress · Profile | `book-education-outline` · `school-outline` · `pencil-box-outline` · `chart-line` · `account-circle-outline` |
| `entertainment_media` | `tabs` | Discover · Watchlist · Now · Library · Profile | `compass-outline` · `bookmark-outline` · `play-circle-outline` · `movie-open-outline` · `account-circle-outline` |
| `finance_money` | `tabs` | Overview · Accounts · Transactions · Budget · Insights | `view-dashboard-outline` · `bank-outline` · `swap-horizontal` · `wallet-outline` · `chart-donut` |
| `food_drink` | `tabs` | Discover · Menu · Reservations · Orders · Profile | `silverware-fork-knife` · `book-open-page-variant-outline` · `calendar-clock-outline` · `receipt-text-outline` · `account-heart-outline` |
| `games` | `tabs` | Home · Quests · Inventory · Friends · Profile | `gamepad-variant-outline` · `flag-outline` · `treasure-chest-outline` · `account-multiple-outline` · `account-circle-outline` |
| `graphics_design` | `drawer` | Dashboard · Briefs · Assets · Reviews · Brand · Settings | `view-dashboard-outline` · `file-document-outline` · `image-multiple-outline` · `comment-check-outline` · `palette-outline` · `cog-outline` |
| `health_fitness` | `tabs` | Today · Plans · Progress · Coach · Profile | `calendar-today-outline` · `clipboard-list-outline` · `chart-line` · `message-processing-outline` · `account-circle-outline` |
| `kids_family` | `tabs` | Home · Routines · Discover · Favorites · Parents | `home-outline` · `calendar-check-outline` · `compass-outline` · `heart-outline` · `shield-account-outline` |
| `lifestyle` | `tabs` | Dashboard · Collections · Plans · Explore · Profile | `view-dashboard-outline` · `bookmark-multiple-outline` · `calendar-star` · `compass-outline` · `account-circle-outline` |
| `medical` | `tabs` | Appointments · Care Team · Records · Messages · Profile | `calendar-check-outline` · `account-heart-outline` · `file-document-outline` · `message-processing-outline` · `account-circle-outline` |
| `music_audio` | `tabs` | Home · Search · Library · Player · Profile | `music-note-outline` · `magnify` · `playlist-music-outline` · `play-circle-outline` · `account-circle-outline` |
| `navigation_travel` | `tabs` | Destinations · Itinerary · Bookings · Map · Profile | `map-marker-outline` · `timeline-outline` · `ticket-outline` · `map-outline` · `account-circle-outline` |
| `news_magazines` | `tabs` | Headlines · Topics · Saved · Search · Profile | `newspaper-variant-outline` · `tag-multiple-outline` · `bookmark-outline` · `magnify` · `account-circle-outline` |
| `photo_video` | `tabs` | Capture · Library · Edit · Share · Profile | `camera-outline` · `image-multiple-outline` · `movie-edit-outline` · `share-variant-outline` · `account-circle-outline` |
| `reference` | `drawer` | Browse · Search · Categories · Saved · History · Settings | `book-open-variant` · `magnify` · `shape-outline` · `bookmark-outline` · `clock-outline` · `cog-outline` |
| `shopping_commerce` | `tabs` | Browse · Search · Sell · Orders · Profile | `shopping-outline` · `magnify` · `store-plus-outline` · `package-variant-closed` · `account-circle-outline` |
| `social_community` | `tabs` | Feed · Groups · Messages · Profile · Settings | `newspaper-variant-outline` · `account-group-outline` · `message-text-outline` · `account-circle-outline` · `cog-outline` |
| `sports` | `tabs` | Scores · Schedule · Standings · Teams · Profile | `scoreboard-outline` · `calendar-month-outline` · `format-list-numbered` · `soccer-field` · `account-circle-outline` |
| `utilities_tools` | `drawer` | Dashboard · Tools · Shortcuts · Storage · Diagnostics · Settings | `view-dashboard-outline` · `wrench-outline` · `lightning-bolt-outline` · `folder-multiple-outline` · `stethoscope` · `cog-outline` |
| `weather` | `tabs` | Now · Forecast · Alerts · Locations | `weather-partly-cloudy` · `weather-cloudy-clock` · `weather-cloudy-alert` · `map-marker-outline` |
The fallback template remains available and is used only for unknown runtime category strings:
- `fallback/default`: Home · Details · Settings (stack)
Additional variants:
- `games/chess`: Home · Settings. The Home screen renders a `ChessBoard` node with a static
initial FEN and requires generated apps to provide `@ankhorage/zora-chess` through their
extension registry.
- `food_drink/nutrition-catalog-scan`: Products · Scan · Capture · Queue · Settings. This
catalog-first Swiss nutrition starter expects API Gateway clients for `GET /v1/nutrition/products`,
`GET /v1/nutrition/products/by-barcode/{barcode}`, and `POST /v1/nutrition/products/capture`.
It intentionally keeps Supabase out of the generated app surface. Native barcode scanning can use
`expo-camera` behind an app adapter, while permission prompts, scan overlays, loading states,
form fields, buttons, notices, and product cards should be composed through ZORA. A reusable
`BarcodeScannerView` / `CameraPermissionView` belongs in ZORA once the scanner API stabilizes,
not in Surface.
- `social_community/creator`: Studio · Posts · Audience · Insights · Settings
Only categories that exist in `AppCategory` are registered. New category literals should be added
in `@ankhorage/contracts` before this package registers templates for them.
## Adding A Category Template
Add category-owned files under `src/templates/starter/categories//`:
- `content.ts` for category-specific copy and placeholder data
- `routes.ts` or `routes..ts` for route names, labels, screen ids, and icons
- `screens.ts` or `screens..ts` for ZORA node trees
- `.template.ts` for manifest assembly
- `index.ts` for `CategoryStarterTemplateDefinition` metadata
Register the category in `src/templates/starter/starter.registry.ts`. Keep shared behavior in
`src/templates/shared/*`; category wording and navigation should stay inside the category folder.
## Verification
```bash
bun run typecheck
bun run build
bun run lint
bun run test
```