Adding the skills

This commit is contained in:
2026-04-01 22:36:42 +02:00
parent 18903f930c
commit addca633e7
7 changed files with 183 additions and 42 deletions
View File
+10
View File
@@ -0,0 +1,10 @@
{
"name": "@glitch-university/glitch-components-workspace",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@glitch-university/glitch-components-workspace"
}
}
}
+21 -11
View File
@@ -27,14 +27,14 @@ function parseArgs(argv) {
const options = {
command,
components: [],
hostDir: '',
hostDirs: [],
stagingDir: path.join(cwd, '.glitch-release')
}
for (let index = 0; index < rest.length; index += 1) {
const arg = rest[index]
if (arg === '--host') {
options.hostDir = path.resolve(cwd, rest[index + 1] ?? '')
options.hostDirs.push(path.resolve(cwd, rest[index + 1] ?? ''))
index += 1
continue
}
@@ -176,6 +176,14 @@ function ensureDirectory(directory) {
fs.mkdirSync(directory, { recursive: true })
}
function getDefaultHostDirs() {
return [
path.resolve(cwd, '..', 'gnommoweb', 'public', 'glitch'),
path.resolve(cwd, '..', 'gnommoplayer', 'public', 'glitch'),
path.resolve(cwd, '..', 'gnommoeditor', 'public', 'glitch')
]
}
function copyDirectoryContents(sourceDir, destinationDir) {
ensureDirectory(destinationDir)
for (const entry of fs.readdirSync(sourceDir)) {
@@ -186,7 +194,7 @@ function copyDirectoryContents(sourceDir, destinationDir) {
}
}
function releaseComponent(component, hostDir, stagingDir) {
function releaseComponent(component, hostDirs, stagingDir) {
const distDir = path.join(component.componentDir, 'dist')
if (!fs.existsSync(distDir)) {
fail(`Missing dist directory for ${component.componentDirName}. Run build first.`)
@@ -205,9 +213,11 @@ function releaseComponent(component, hostDir, stagingDir) {
tags: ['legacy']
}
const releaseDir = path.join(hostDir, manifest.folderName)
copyDirectoryContents(distDir, releaseDir)
fs.writeFileSync(path.join(releaseDir, 'glitch.manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`)
for (const hostDir of hostDirs) {
const releaseDir = path.join(hostDir, manifest.folderName)
copyDirectoryContents(distDir, releaseDir)
fs.writeFileSync(path.join(releaseDir, 'glitch.manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`)
}
const stagingComponentDir = path.join(stagingDir, manifest.folderName)
copyDirectoryContents(distDir, stagingComponentDir)
@@ -268,17 +278,17 @@ switch (options.command) {
}
case 'release': {
const hostDir =
options.hostDir ||
path.resolve(cwd, '..', 'gnommoweb', 'src', 'components', 'glitch')
const hostDirs = options.hostDirs.length > 0 ? options.hostDirs : getDefaultHostDirs()
ensureDirectory(hostDir)
for (const hostDir of hostDirs) {
ensureDirectory(hostDir)
}
ensureDirectory(options.stagingDir)
for (const component of components) {
console.log(`=== Releasing ${component.componentDirName} ===`)
runBuild(component)
releaseComponent(component, hostDir, options.stagingDir)
releaseComponent(component, hostDirs, options.stagingDir)
}
break
}
+12 -31
View File
@@ -1,12 +1,4 @@
#!/bin/bash
# Sets up git remotes for all glitch-component folders and pushes to ramanujan.
#
# Usage:
# ./setup-remotes.sh # set remotes only
# ./setup-remotes.sh --push # set remotes and push all
#
# Reads GIT_USER / GIT_PASSWORD from ../.env if present, otherwise prompts.
set -e
REMOTE_HOST="ramanujan.glitch.university"
@@ -14,34 +6,17 @@ COMPONENTS_DIR="$(cd "$(dirname "$0")" && pwd)"
PUSH=false
[[ "$1" == "--push" ]] && PUSH=true
# ── Load credentials ──────────────────────────────────────────────────────────
REMOTE_BASE="ssh://git@${REMOTE_HOST}/git/repos"
ENV_FILE="$COMPONENTS_DIR/../gnommoweb/.env.prod"
if [ -f "$ENV_FILE" ]; then
GIT_USER=$(grep -E '^GIT_USER=' "$ENV_FILE" | cut -d= -f2 | tr -d '"'"'" | head -1)
GIT_PASSWORD=$(grep -E '^GIT_PASSWORD=' "$ENV_FILE" | cut -d= -f2 | tr -d '"'"'" | head -1)
fi
if [ -z "$GIT_USER" ] || [ -z "$GIT_PASSWORD" ]; then
read -rp "Git username: " GIT_USER
read -rsp "Git password: " GIT_PASSWORD
echo
fi
REMOTE_BASE="https://${GIT_USER}:${GIT_PASSWORD}@${REMOTE_HOST}"
# ── Process each component folder ─────────────────────────────────────────────
for dir in "$COMPONENTS_DIR"/*/; do
name=$(basename "$dir")
# Skip the skills folder and any non-component entries
[[ "$name" == "skills" ]] && continue
echo "── $name"
cd "$dir"
# Init if not already a git repo
if [ ! -d ".git" ]; then
git init -q
git add -A
@@ -49,21 +24,27 @@ for dir in "$COMPONENTS_DIR"/*/; do
echo " initialised"
fi
# Add or update remote
REMOTE_URL="https://${REMOTE_HOST}/${name}.git"
if git remote get-url origin &>/dev/null; then
git remote set-url origin "${REMOTE_BASE}/${name}.git"
git remote set-url origin "$REMOTE_URL"
echo " remote updated"
else
git remote add origin "${REMOTE_BASE}/${name}.git"
git remote add origin "$REMOTE_URL"
echo " remote added"
fi
# Push
if $PUSH; then
if ssh git@"$REMOTE_HOST" create-repo "${name}.git" 2>/dev/null; then
echo " remote repo ensured"
else
echo " remote repo may already exist"
fi
if git push -u origin main -q 2>/dev/null || git push -u origin master:main -q 2>/dev/null; then
echo " pushed"
else
echo " push failed (repo may not exist on server yet)"
echo " push failed"
fi
fi
+92
View File
@@ -0,0 +1,92 @@
# GlitchComponent Contract (Canonical Shape)
Use the local `lightlane` project as the canonical source when available:
- `../lightlane/src/types.ts`
- `../lightlane/src/index.tsx`
This reference captures the current shape observed in `lightlane` so the skill can scaffold quickly.
## Required Exports
`src/index.tsx` should export:
- `default` component
- `metadata` object (`GlitchComponentMetadata`)
- relevant types re-exported from `src/types.ts`
## Core Types (Current Lightlane-Compatible Shape)
```ts
export interface GlitchComponentConfig {
id: string;
name: string;
version: string;
params: Record<string, unknown>;
}
export interface GlitchTheme {
primary: string;
accent: string;
bg: string;
bgSecondary: string;
text: string;
textMuted: string;
border: string;
}
export interface GlitchComponentResult {
success: boolean;
score?: number;
data?: unknown;
error?: string;
}
export interface GlitchComponentProps {
config: GlitchComponentConfig;
onComplete: (result: GlitchComponentResult) => void;
onProgress?: (percent: number) => void;
theme?: GlitchTheme;
className?: string;
}
export interface ParamSchema {
[key: string]: {
type: 'number' | 'string' | 'boolean' | 'color' | 'select' | 'range';
label?: string;
description?: string;
default: unknown;
options?: { value: string | number; label: string }[];
min?: number;
max?: number;
step?: number;
};
}
export interface GlitchComponentMetadata {
name: string;
displayName: string;
version: string;
paramSchema: ParamSchema;
defaultParams: Record<string, unknown>;
}
```
## Metadata Expectations
- `name`: kebab-case slug used by host registration
- `displayName`: human-friendly title
- `version`: semantic version string
- `paramSchema`: controls/settings schema for host and dev harness
- `defaultParams`: values that produce a working component without additional configuration
## Behavioral Expectations
- Call `onComplete(...)` when the experience completes or fails definitively.
- Call `onProgress(percent)` for multi-step flows when progress is meaningful.
- Use `config.params` as the single source of runtime config.
- Respect `theme` if provided, but keep fallbacks for standalone mode.
## Validation Tip
Before finalizing a scaffold, compare generated `src/types.ts` and `src/index.tsx` against the current `../lightlane/src/types.ts` and `../lightlane/src/index.tsx` to catch drift.
+14
View File
@@ -0,0 +1,14 @@
# Create GlitchComponent
The canonical Glitch University component workflow now lives at the workspace root:
- `/Users/jenstandstad/Projects/glitch-components/GLITCH_COMPONENT_STANDARD.md`
- `/Users/jenstandstad/Projects/glitch-components/templates/react-vite-glitch-component/`
- `/Users/jenstandstad/Projects/glitch-components/scripts/new-glitch-component.mjs`
Use the root scaffold instead of copying this folder or reusing older component boilerplate.
For special features suchas 3D, Sound bridge etc consider the referenes in
/Users/jenstandstad/Projects/glitch-components/skills/references
+34
View File
@@ -0,0 +1,34 @@
# Sound Bridge Notes
Glitch University uses a host-managed sound system (Howler-based) with string sound keys, for example:
- `playSound('ui.button_click')`
- `playSound('ui.button_hover')`
## Recommendation
Treat sound as an optional host integration:
- Use a small wrapper function in the component (`safePlaySound`) that checks whether a host sound function exists.
- No-op when unavailable (standalone dev should still run).
- Keep sound identifiers as strings/constants so they match host definitions.
## Example Pattern
```ts
type PlaySound = (id: string) => void;
export function safePlaySound(playSound: PlaySound | undefined, id: string) {
try {
playSound?.(id);
} catch {
// Ignore host sound errors in standalone/local mode
}
}
```
## Unknowns to Confirm Later
- How the host exposes `playSound` to glitch-components (prop, context, global import, event bus)
- Which sound keys are safe/standardized across experiences
- Whether completion/reward sounds are triggered by host or component