@lampdotdev/lamp 0.0.0-stage → 0.35.0

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.
Files changed (464) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -2
  3. package/Resources/Devices/roku.json +410 -0
  4. package/Resources/Devices/xbox-one.json +367 -0
  5. package/Resources/GameKit/NOTICE.md +63 -0
  6. package/Resources/GameKit/apple/LampPage.swift +1646 -0
  7. package/Resources/GameKit/apple/LampPlayer.swift +46 -0
  8. package/Resources/GameKit/apple/LampWebApp.swift +63 -0
  9. package/Resources/GameKit/apple/LampWebGame.swift +87 -0
  10. package/Resources/GameKit/apple/Native.swift +12 -0
  11. package/Resources/GameKit/build.sh +55 -0
  12. package/Resources/GameKit/lamp_game.h +116 -0
  13. package/Resources/GameKit/lamp_host.h +19 -0
  14. package/Resources/GameKit/lamp_kit.cpp +61 -0
  15. package/Resources/GameKit/lamp_sound.cpp +455 -0
  16. package/Resources/GameKit/lamp_xbox.cpp +374 -0
  17. package/Resources/GameKit/libraries/HandmadeMath.h +3940 -0
  18. package/Resources/GameKit/libraries/cgltf.h +7240 -0
  19. package/Resources/GameKit/libraries/dr_mp3.h +5430 -0
  20. package/Resources/GameKit/libraries/dr_wav.h +9209 -0
  21. package/Resources/GameKit/libraries/sokol_debugtext.h +4754 -0
  22. package/Resources/GameKit/libraries/sokol_gfx.h +29558 -0
  23. package/Resources/GameKit/libraries/sokol_gl.h +4538 -0
  24. package/Resources/GameKit/libraries/sokol_log.h +335 -0
  25. package/Resources/GameKit/libraries/sokol_shape.h +1531 -0
  26. package/Resources/GameKit/libraries/stb_image.h +7988 -0
  27. package/Resources/GameKit/libraries/stb_vorbis.c +5584 -0
  28. package/Resources/GameKit/scaffold/Game/game.cpp +142 -0
  29. package/Resources/GameKit/scaffold/Game/scene.glsl +49 -0
  30. package/Resources/GameKit/scaffold-web/Web/game.js +31 -0
  31. package/Resources/GameKit/scaffold-web/Web/index.html +13 -0
  32. package/Resources/GameKit/scaffold-web/Web/making.js +33 -0
  33. package/Resources/GameKit/scaffold-web/Web/world.js +33 -0
  34. package/Resources/GameKit/web/lamp-game.js +3036 -0
  35. package/Resources/GameKit/web/lamp-phaser.js +128 -0
  36. package/Resources/WebHost/App.exe +0 -0
  37. package/Resources/WebHost/Microsoft.Web.WebView2.Core.dll +0 -0
  38. package/Resources/WebHost/WebView2-LICENSE.txt +27 -0
  39. package/Resources/WebHost/lamp_controllers.h +1506 -0
  40. package/Resources/WebHost/lamp_web_host.cpp +1173 -0
  41. package/Resources/WebLibraries/earlier.txt +318 -0
  42. package/Resources/WebLibraries/phaser/LICENSE.md +20 -0
  43. package/Resources/WebLibraries/phaser/NOTICE.md +2 -0
  44. package/Resources/WebLibraries/phaser/phaser.esm.min.js +1 -0
  45. package/Resources/WebLibraries/qrcode/LICENSE +21 -0
  46. package/Resources/WebLibraries/qrcode/NOTICE.md +4 -0
  47. package/Resources/WebLibraries/qrcode/qrcode.js +2297 -0
  48. package/Resources/WebLibraries/rapier/LICENSE +201 -0
  49. package/Resources/WebLibraries/rapier/NOTICE.md +3 -0
  50. package/Resources/WebLibraries/rapier/rapier.js +2 -0
  51. package/Resources/WebLibraries/three/LICENSE +21 -0
  52. package/Resources/WebLibraries/three/NOTICE.md +4 -0
  53. package/Resources/WebLibraries/three/addons/animation/AnimationClipCreator.js +168 -0
  54. package/Resources/WebLibraries/three/addons/animation/CCDIKSolver.js +607 -0
  55. package/Resources/WebLibraries/three/addons/controls/ArcballControls.js +3543 -0
  56. package/Resources/WebLibraries/three/addons/controls/DragControls.js +452 -0
  57. package/Resources/WebLibraries/three/addons/controls/FirstPersonControls.js +512 -0
  58. package/Resources/WebLibraries/three/addons/controls/FlyControls.js +384 -0
  59. package/Resources/WebLibraries/three/addons/controls/MapControls.js +116 -0
  60. package/Resources/WebLibraries/three/addons/controls/OrbitControls.js +1985 -0
  61. package/Resources/WebLibraries/three/addons/controls/PointerLockControls.js +264 -0
  62. package/Resources/WebLibraries/three/addons/controls/TrackballControls.js +1106 -0
  63. package/Resources/WebLibraries/three/addons/controls/TransformControls.js +2003 -0
  64. package/Resources/WebLibraries/three/addons/curves/CurveExtras.js +694 -0
  65. package/Resources/WebLibraries/three/addons/curves/NURBSCurve.js +169 -0
  66. package/Resources/WebLibraries/three/addons/curves/NURBSSurface.js +98 -0
  67. package/Resources/WebLibraries/three/addons/curves/NURBSUtils.js +532 -0
  68. package/Resources/WebLibraries/three/addons/curves/NURBSVolume.js +82 -0
  69. package/Resources/WebLibraries/three/addons/effects/AnaglyphEffect.js +274 -0
  70. package/Resources/WebLibraries/three/addons/effects/AsciiEffect.js +323 -0
  71. package/Resources/WebLibraries/three/addons/effects/OutlineEffect.js +489 -0
  72. package/Resources/WebLibraries/three/addons/effects/ParallaxBarrierEffect.js +155 -0
  73. package/Resources/WebLibraries/three/addons/effects/StereoEffect.js +91 -0
  74. package/Resources/WebLibraries/three/addons/environments/ColorEnvironment.js +59 -0
  75. package/Resources/WebLibraries/three/addons/environments/DebugEnvironment.js +102 -0
  76. package/Resources/WebLibraries/three/addons/environments/RoomEnvironment.js +185 -0
  77. package/Resources/WebLibraries/three/addons/geometries/BoxLineGeometry.js +92 -0
  78. package/Resources/WebLibraries/three/addons/geometries/ConvexGeometry.js +72 -0
  79. package/Resources/WebLibraries/three/addons/geometries/DecalGeometry.js +420 -0
  80. package/Resources/WebLibraries/three/addons/geometries/LoftGeometry.js +355 -0
  81. package/Resources/WebLibraries/three/addons/geometries/ParametricFunctions.js +100 -0
  82. package/Resources/WebLibraries/three/addons/geometries/ParametricGeometry.js +172 -0
  83. package/Resources/WebLibraries/three/addons/geometries/RoundedBoxGeometry.js +216 -0
  84. package/Resources/WebLibraries/three/addons/geometries/TeapotGeometry.js +689 -0
  85. package/Resources/WebLibraries/three/addons/geometries/TextGeometry.js +102 -0
  86. package/Resources/WebLibraries/three/addons/helpers/AnimationPathHelper.js +302 -0
  87. package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelper.js +166 -0
  88. package/Resources/WebLibraries/three/addons/helpers/LightProbeGridHelperWebGL.js +221 -0
  89. package/Resources/WebLibraries/three/addons/helpers/LightProbeHelper.js +166 -0
  90. package/Resources/WebLibraries/three/addons/helpers/LightProbeHelperGPU.js +102 -0
  91. package/Resources/WebLibraries/three/addons/helpers/OctreeHelper.js +109 -0
  92. package/Resources/WebLibraries/three/addons/helpers/PositionalAudioHelper.js +169 -0
  93. package/Resources/WebLibraries/three/addons/helpers/RapierHelper.js +59 -0
  94. package/Resources/WebLibraries/three/addons/helpers/RectAreaLightHelper.js +118 -0
  95. package/Resources/WebLibraries/three/addons/helpers/TextureHelper.js +265 -0
  96. package/Resources/WebLibraries/three/addons/helpers/TextureHelperGPU.js +214 -0
  97. package/Resources/WebLibraries/three/addons/helpers/VertexNormalsHelper.js +155 -0
  98. package/Resources/WebLibraries/three/addons/helpers/VertexTangentsHelper.js +133 -0
  99. package/Resources/WebLibraries/three/addons/helpers/ViewHelper.js +529 -0
  100. package/Resources/WebLibraries/three/addons/interactive/HTMLMesh.js +617 -0
  101. package/Resources/WebLibraries/three/addons/interactive/InteractiveGroup.js +224 -0
  102. package/Resources/WebLibraries/three/addons/interactive/SelectionBox.js +324 -0
  103. package/Resources/WebLibraries/three/addons/interactive/SelectionHelper.js +150 -0
  104. package/Resources/WebLibraries/three/addons/libs/fflate.module.js +2699 -0
  105. package/Resources/WebLibraries/three/addons/libs/lil-gui.module.min.js +8 -0
  106. package/Resources/WebLibraries/three/addons/libs/meshopt_decoder.module.js +196 -0
  107. package/Resources/WebLibraries/three/addons/libs/potpack.module.js +125 -0
  108. package/Resources/WebLibraries/three/addons/libs/stats.module.js +167 -0
  109. package/Resources/WebLibraries/three/addons/libs/tween.module.js +876 -0
  110. package/Resources/WebLibraries/three/addons/lighting/ClusteredLighting.js +153 -0
  111. package/Resources/WebLibraries/three/addons/lighting/DynamicLighting.js +82 -0
  112. package/Resources/WebLibraries/three/addons/lighting/LightMapper.js +295 -0
  113. package/Resources/WebLibraries/three/addons/lighting/LightProbeGrid.js +923 -0
  114. package/Resources/WebLibraries/three/addons/lighting/LightProbeGridUtils.js +107 -0
  115. package/Resources/WebLibraries/three/addons/lighting/LightProbeGridWebGL.js +846 -0
  116. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIConeTracer.js +243 -0
  117. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIIrradiance.js +43 -0
  118. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGINode.js +617 -0
  119. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGISceneCollector.js +793 -0
  120. package/Resources/WebLibraries/three/addons/lighting/vxgi/VXGIVolume.js +1440 -0
  121. package/Resources/WebLibraries/three/addons/lights/LightProbeGenerator.js +337 -0
  122. package/Resources/WebLibraries/three/addons/lights/RectAreaLightTexturesLib.js +127 -0
  123. package/Resources/WebLibraries/three/addons/lights/RectAreaLightUniformsLib.js +40 -0
  124. package/Resources/WebLibraries/three/addons/lights/SunLight.js +100 -0
  125. package/Resources/WebLibraries/three/addons/lights/SunLightNode.js +56 -0
  126. package/Resources/WebLibraries/three/addons/lights/SunLightShadow.js +319 -0
  127. package/Resources/WebLibraries/three/addons/lights/SunShadowNode.js +312 -0
  128. package/Resources/WebLibraries/three/addons/lines/Line2.js +56 -0
  129. package/Resources/WebLibraries/three/addons/lines/LineGeometry.js +157 -0
  130. package/Resources/WebLibraries/three/addons/lines/LineMaterial.js +742 -0
  131. package/Resources/WebLibraries/three/addons/lines/LineSegments2.js +434 -0
  132. package/Resources/WebLibraries/three/addons/lines/LineSegmentsGeometry.js +298 -0
  133. package/Resources/WebLibraries/three/addons/lines/Wireframe.js +108 -0
  134. package/Resources/WebLibraries/three/addons/lines/WireframeGeometry2.js +49 -0
  135. package/Resources/WebLibraries/three/addons/lines/webgpu/Line2.js +46 -0
  136. package/Resources/WebLibraries/three/addons/lines/webgpu/LineSegments2.js +419 -0
  137. package/Resources/WebLibraries/three/addons/lines/webgpu/Wireframe.js +86 -0
  138. package/Resources/WebLibraries/three/addons/loaders/EXRLoader.js +3411 -0
  139. package/Resources/WebLibraries/three/addons/loaders/FBXLoader.js +4660 -0
  140. package/Resources/WebLibraries/three/addons/loaders/FontLoader.js +262 -0
  141. package/Resources/WebLibraries/three/addons/loaders/GLTFLoader.js +5006 -0
  142. package/Resources/WebLibraries/three/addons/loaders/HDRLoader.js +463 -0
  143. package/Resources/WebLibraries/three/addons/loaders/MTLLoader.js +601 -0
  144. package/Resources/WebLibraries/three/addons/loaders/OBJLoader.js +961 -0
  145. package/Resources/WebLibraries/three/addons/loaders/PLYLoader.js +992 -0
  146. package/Resources/WebLibraries/three/addons/loaders/RGBELoader.js +18 -0
  147. package/Resources/WebLibraries/three/addons/loaders/STLLoader.js +423 -0
  148. package/Resources/WebLibraries/three/addons/loaders/SVGLoader.js +3297 -0
  149. package/Resources/WebLibraries/three/addons/loaders/TGALoader.js +539 -0
  150. package/Resources/WebLibraries/three/addons/loaders/UltraHDRLoader.js +757 -0
  151. package/Resources/WebLibraries/three/addons/math/Capsule.js +159 -0
  152. package/Resources/WebLibraries/three/addons/math/ColorConverter.js +62 -0
  153. package/Resources/WebLibraries/three/addons/math/ColorSpaces.js +147 -0
  154. package/Resources/WebLibraries/three/addons/math/ConvexHull.js +1695 -0
  155. package/Resources/WebLibraries/three/addons/math/ImprovedNoise.js +88 -0
  156. package/Resources/WebLibraries/three/addons/math/Lut.js +317 -0
  157. package/Resources/WebLibraries/three/addons/math/MeshSurfaceSampler.js +315 -0
  158. package/Resources/WebLibraries/three/addons/math/OBB.js +535 -0
  159. package/Resources/WebLibraries/three/addons/math/Octree.js +825 -0
  160. package/Resources/WebLibraries/three/addons/math/SimplexNoise.js +470 -0
  161. package/Resources/WebLibraries/three/addons/misc/ConvexObjectBreaker.js +539 -0
  162. package/Resources/WebLibraries/three/addons/misc/GPUComputationRenderer.js +508 -0
  163. package/Resources/WebLibraries/three/addons/misc/Gyroscope.js +78 -0
  164. package/Resources/WebLibraries/three/addons/misc/MorphAnimMesh.js +119 -0
  165. package/Resources/WebLibraries/three/addons/misc/MorphBlendMesh.js +425 -0
  166. package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMap.js +370 -0
  167. package/Resources/WebLibraries/three/addons/misc/ProgressiveLightMapGPU.js +322 -0
  168. package/Resources/WebLibraries/three/addons/misc/RollerCoaster.js +661 -0
  169. package/Resources/WebLibraries/three/addons/misc/Sculptor.js +1679 -0
  170. package/Resources/WebLibraries/three/addons/misc/SculptorMesh.js +1504 -0
  171. package/Resources/WebLibraries/three/addons/misc/SculptorTools.js +1180 -0
  172. package/Resources/WebLibraries/three/addons/misc/SculptorUtils.js +345 -0
  173. package/Resources/WebLibraries/three/addons/misc/TileCreasedNormalsPlugin.js +270 -0
  174. package/Resources/WebLibraries/three/addons/misc/TubePainter.js +611 -0
  175. package/Resources/WebLibraries/three/addons/misc/Volume.js +520 -0
  176. package/Resources/WebLibraries/three/addons/misc/VolumeSlice.js +275 -0
  177. package/Resources/WebLibraries/three/addons/modifiers/CurveModifier.js +374 -0
  178. package/Resources/WebLibraries/three/addons/modifiers/CurveModifierGPU.js +256 -0
  179. package/Resources/WebLibraries/three/addons/modifiers/EdgeSplitModifier.js +299 -0
  180. package/Resources/WebLibraries/three/addons/modifiers/TessellateModifier.js +340 -0
  181. package/Resources/WebLibraries/three/addons/objects/GroundedSkybox.js +69 -0
  182. package/Resources/WebLibraries/three/addons/objects/Lensflare.js +489 -0
  183. package/Resources/WebLibraries/three/addons/objects/LensflareMesh.js +376 -0
  184. package/Resources/WebLibraries/three/addons/objects/MarchingCubes.js +1261 -0
  185. package/Resources/WebLibraries/three/addons/objects/Reflector.js +390 -0
  186. package/Resources/WebLibraries/three/addons/objects/ReflectorForSSRPass.js +393 -0
  187. package/Resources/WebLibraries/three/addons/objects/Refractor.js +389 -0
  188. package/Resources/WebLibraries/three/addons/objects/ShadowMesh.js +130 -0
  189. package/Resources/WebLibraries/three/addons/objects/Sky.js +342 -0
  190. package/Resources/WebLibraries/three/addons/objects/SkyMesh.js +403 -0
  191. package/Resources/WebLibraries/three/addons/objects/Water.js +374 -0
  192. package/Resources/WebLibraries/three/addons/objects/Water2.js +403 -0
  193. package/Resources/WebLibraries/three/addons/objects/Water2Mesh.js +199 -0
  194. package/Resources/WebLibraries/three/addons/objects/WaterMesh.js +194 -0
  195. package/Resources/WebLibraries/three/addons/postprocessing/AfterimagePass.js +187 -0
  196. package/Resources/WebLibraries/three/addons/postprocessing/BloomPass.js +274 -0
  197. package/Resources/WebLibraries/three/addons/postprocessing/BokehPass.js +218 -0
  198. package/Resources/WebLibraries/three/addons/postprocessing/ClearPass.js +97 -0
  199. package/Resources/WebLibraries/three/addons/postprocessing/CubeTexturePass.js +146 -0
  200. package/Resources/WebLibraries/three/addons/postprocessing/DotScreenPass.js +114 -0
  201. package/Resources/WebLibraries/three/addons/postprocessing/EffectComposer.js +365 -0
  202. package/Resources/WebLibraries/three/addons/postprocessing/FXAAPass.js +40 -0
  203. package/Resources/WebLibraries/three/addons/postprocessing/FilmPass.js +113 -0
  204. package/Resources/WebLibraries/three/addons/postprocessing/GTAOPass.js +735 -0
  205. package/Resources/WebLibraries/three/addons/postprocessing/GlitchPass.js +177 -0
  206. package/Resources/WebLibraries/three/addons/postprocessing/HalftonePass.js +134 -0
  207. package/Resources/WebLibraries/three/addons/postprocessing/LUTPass.js +138 -0
  208. package/Resources/WebLibraries/three/addons/postprocessing/MaskPass.js +195 -0
  209. package/Resources/WebLibraries/three/addons/postprocessing/OutlinePass.js +776 -0
  210. package/Resources/WebLibraries/three/addons/postprocessing/OutputPass.js +148 -0
  211. package/Resources/WebLibraries/three/addons/postprocessing/Pass.js +191 -0
  212. package/Resources/WebLibraries/three/addons/postprocessing/RenderPass.js +193 -0
  213. package/Resources/WebLibraries/three/addons/postprocessing/RenderPixelatedPass.js +314 -0
  214. package/Resources/WebLibraries/three/addons/postprocessing/RenderTransitionPass.js +267 -0
  215. package/Resources/WebLibraries/three/addons/postprocessing/SAOPass.js +407 -0
  216. package/Resources/WebLibraries/three/addons/postprocessing/SMAAPass.js +230 -0
  217. package/Resources/WebLibraries/three/addons/postprocessing/SSAARenderPass.js +313 -0
  218. package/Resources/WebLibraries/three/addons/postprocessing/SSAOPass.js +527 -0
  219. package/Resources/WebLibraries/three/addons/postprocessing/SSRPass.js +858 -0
  220. package/Resources/WebLibraries/three/addons/postprocessing/SavePass.js +132 -0
  221. package/Resources/WebLibraries/three/addons/postprocessing/ShaderPass.js +135 -0
  222. package/Resources/WebLibraries/three/addons/postprocessing/TAARenderPass.js +243 -0
  223. package/Resources/WebLibraries/three/addons/postprocessing/TexturePass.js +131 -0
  224. package/Resources/WebLibraries/three/addons/postprocessing/UnrealBloomPass.js +541 -0
  225. package/Resources/WebLibraries/three/addons/shaders/ACESFilmicToneMappingShader.js +96 -0
  226. package/Resources/WebLibraries/three/addons/shaders/AfterimageShader.js +63 -0
  227. package/Resources/WebLibraries/three/addons/shaders/BasicShader.js +36 -0
  228. package/Resources/WebLibraries/three/addons/shaders/BleachBypassShader.js +68 -0
  229. package/Resources/WebLibraries/three/addons/shaders/BlendShader.js +56 -0
  230. package/Resources/WebLibraries/three/addons/shaders/BokehShader.js +151 -0
  231. package/Resources/WebLibraries/three/addons/shaders/BokehShader2.js +404 -0
  232. package/Resources/WebLibraries/three/addons/shaders/BrightnessContrastShader.js +62 -0
  233. package/Resources/WebLibraries/three/addons/shaders/ColorCorrectionShader.js +59 -0
  234. package/Resources/WebLibraries/three/addons/shaders/ColorifyShader.js +57 -0
  235. package/Resources/WebLibraries/three/addons/shaders/ConvolutionShader.js +74 -0
  236. package/Resources/WebLibraries/three/addons/shaders/CopyShader.js +52 -0
  237. package/Resources/WebLibraries/three/addons/shaders/DOFMipMapShader.js +63 -0
  238. package/Resources/WebLibraries/three/addons/shaders/DepthLimitedBlurShader.js +183 -0
  239. package/Resources/WebLibraries/three/addons/shaders/DigitalGlitch.js +104 -0
  240. package/Resources/WebLibraries/three/addons/shaders/DotScreenShader.js +75 -0
  241. package/Resources/WebLibraries/three/addons/shaders/ExposureShader.js +51 -0
  242. package/Resources/WebLibraries/three/addons/shaders/FXAAShader.js +298 -0
  243. package/Resources/WebLibraries/three/addons/shaders/FilmShader.js +73 -0
  244. package/Resources/WebLibraries/three/addons/shaders/FocusShader.js +94 -0
  245. package/Resources/WebLibraries/three/addons/shaders/FreiChenShader.js +103 -0
  246. package/Resources/WebLibraries/three/addons/shaders/GTAOShader.js +437 -0
  247. package/Resources/WebLibraries/three/addons/shaders/GammaCorrectionShader.js +52 -0
  248. package/Resources/WebLibraries/three/addons/shaders/HalftoneShader.js +332 -0
  249. package/Resources/WebLibraries/three/addons/shaders/HorizontalBlurShader.js +68 -0
  250. package/Resources/WebLibraries/three/addons/shaders/HorizontalTiltShiftShader.js +70 -0
  251. package/Resources/WebLibraries/three/addons/shaders/HueSaturationShader.js +74 -0
  252. package/Resources/WebLibraries/three/addons/shaders/KaleidoShader.js +65 -0
  253. package/Resources/WebLibraries/three/addons/shaders/LuminosityHighPassShader.js +68 -0
  254. package/Resources/WebLibraries/three/addons/shaders/LuminosityShader.js +54 -0
  255. package/Resources/WebLibraries/three/addons/shaders/MirrorShader.js +62 -0
  256. package/Resources/WebLibraries/three/addons/shaders/NormalMapShader.js +60 -0
  257. package/Resources/WebLibraries/three/addons/shaders/OutputShader.js +103 -0
  258. package/Resources/WebLibraries/three/addons/shaders/PoissonDenoiseShader.js +230 -0
  259. package/Resources/WebLibraries/three/addons/shaders/RGBShiftShader.js +61 -0
  260. package/Resources/WebLibraries/three/addons/shaders/SAOShader.js +201 -0
  261. package/Resources/WebLibraries/three/addons/shaders/SMAAShader.js +489 -0
  262. package/Resources/WebLibraries/three/addons/shaders/SSAOShader.js +331 -0
  263. package/Resources/WebLibraries/three/addons/shaders/SSRShader.js +396 -0
  264. package/Resources/WebLibraries/three/addons/shaders/SepiaShader.js +57 -0
  265. package/Resources/WebLibraries/three/addons/shaders/SobelOperatorShader.js +98 -0
  266. package/Resources/WebLibraries/three/addons/shaders/SubsurfaceScatteringShader.js +95 -0
  267. package/Resources/WebLibraries/three/addons/shaders/TechnicolorShader.js +51 -0
  268. package/Resources/WebLibraries/three/addons/shaders/ToonShader.js +349 -0
  269. package/Resources/WebLibraries/three/addons/shaders/TriangleBlurShader.js +79 -0
  270. package/Resources/WebLibraries/three/addons/shaders/UnpackDepthRGBAShader.js +60 -0
  271. package/Resources/WebLibraries/three/addons/shaders/VelocityShader.js +137 -0
  272. package/Resources/WebLibraries/three/addons/shaders/VerticalBlurShader.js +66 -0
  273. package/Resources/WebLibraries/three/addons/shaders/VerticalTiltShiftShader.js +70 -0
  274. package/Resources/WebLibraries/three/addons/shaders/VignetteShader.js +56 -0
  275. package/Resources/WebLibraries/three/addons/shaders/VolumeShader.js +285 -0
  276. package/Resources/WebLibraries/three/addons/shaders/WaterRefractionShader.js +106 -0
  277. package/Resources/WebLibraries/three/addons/textures/FlakesTexture.js +54 -0
  278. package/Resources/WebLibraries/three/addons/tsl/WebGLNodesHandler.js +607 -0
  279. package/Resources/WebLibraries/three/addons/tsl/display/AfterImageNode.js +256 -0
  280. package/Resources/WebLibraries/three/addons/tsl/display/AnaglyphPassNode.js +550 -0
  281. package/Resources/WebLibraries/three/addons/tsl/display/BilateralBlurNode.js +377 -0
  282. package/Resources/WebLibraries/three/addons/tsl/display/BleachBypass.js +33 -0
  283. package/Resources/WebLibraries/three/addons/tsl/display/BloomNode.js +599 -0
  284. package/Resources/WebLibraries/three/addons/tsl/display/CRT.js +150 -0
  285. package/Resources/WebLibraries/three/addons/tsl/display/ChromaticAberrationNode.js +163 -0
  286. package/Resources/WebLibraries/three/addons/tsl/display/DenoiseNode.js +354 -0
  287. package/Resources/WebLibraries/three/addons/tsl/display/DepthOfFieldNode.js +572 -0
  288. package/Resources/WebLibraries/three/addons/tsl/display/DotScreenNode.js +104 -0
  289. package/Resources/WebLibraries/three/addons/tsl/display/FSR1Node.js +481 -0
  290. package/Resources/WebLibraries/three/addons/tsl/display/FXAANode.js +357 -0
  291. package/Resources/WebLibraries/three/addons/tsl/display/FilmNode.js +101 -0
  292. package/Resources/WebLibraries/three/addons/tsl/display/GTAONode.js +727 -0
  293. package/Resources/WebLibraries/three/addons/tsl/display/GaussianBlurNode.js +412 -0
  294. package/Resources/WebLibraries/three/addons/tsl/display/GodraysNode.js +604 -0
  295. package/Resources/WebLibraries/three/addons/tsl/display/ImportanceSampledEnvironment.js +564 -0
  296. package/Resources/WebLibraries/three/addons/tsl/display/LensflareNode.js +282 -0
  297. package/Resources/WebLibraries/three/addons/tsl/display/Lut3DNode.js +109 -0
  298. package/Resources/WebLibraries/three/addons/tsl/display/MotionBlur.js +33 -0
  299. package/Resources/WebLibraries/three/addons/tsl/display/OITPassNode.js +341 -0
  300. package/Resources/WebLibraries/three/addons/tsl/display/OutlineNode.js +916 -0
  301. package/Resources/WebLibraries/three/addons/tsl/display/ParallaxBarrierPassNode.js +90 -0
  302. package/Resources/WebLibraries/three/addons/tsl/display/PixelationPassNode.js +227 -0
  303. package/Resources/WebLibraries/three/addons/tsl/display/RGBShiftNode.js +96 -0
  304. package/Resources/WebLibraries/three/addons/tsl/display/RecurrentDenoiseNode.js +812 -0
  305. package/Resources/WebLibraries/three/addons/tsl/display/RetroPassNode.js +263 -0
  306. package/Resources/WebLibraries/three/addons/tsl/display/SMAANode.js +729 -0
  307. package/Resources/WebLibraries/three/addons/tsl/display/SSAAPassNode.js +344 -0
  308. package/Resources/WebLibraries/three/addons/tsl/display/SSAONode.js +422 -0
  309. package/Resources/WebLibraries/three/addons/tsl/display/SSGINode.js +698 -0
  310. package/Resources/WebLibraries/three/addons/tsl/display/SSRNode.js +1430 -0
  311. package/Resources/WebLibraries/three/addons/tsl/display/SSSNode.js +479 -0
  312. package/Resources/WebLibraries/three/addons/tsl/display/Sepia.js +24 -0
  313. package/Resources/WebLibraries/three/addons/tsl/display/Shape.js +29 -0
  314. package/Resources/WebLibraries/three/addons/tsl/display/SharpenNode.js +284 -0
  315. package/Resources/WebLibraries/three/addons/tsl/display/SobelOperatorNode.js +168 -0
  316. package/Resources/WebLibraries/three/addons/tsl/display/StereoCompositePassNode.js +190 -0
  317. package/Resources/WebLibraries/three/addons/tsl/display/StereoPassNode.js +117 -0
  318. package/Resources/WebLibraries/three/addons/tsl/display/TAAUNode.js +700 -0
  319. package/Resources/WebLibraries/three/addons/tsl/display/TRAANode.js +609 -0
  320. package/Resources/WebLibraries/three/addons/tsl/display/TemporalReprojectNode.js +1024 -0
  321. package/Resources/WebLibraries/three/addons/tsl/display/TransitionNode.js +141 -0
  322. package/Resources/WebLibraries/three/addons/tsl/display/boxBlur.js +65 -0
  323. package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlend.js +80 -0
  324. package/Resources/WebLibraries/three/addons/tsl/display/depthAwareBlur.js +63 -0
  325. package/Resources/WebLibraries/three/addons/tsl/display/hashBlur.js +55 -0
  326. package/Resources/WebLibraries/three/addons/tsl/display/lensDirt.js +30 -0
  327. package/Resources/WebLibraries/three/addons/tsl/display/radialBlur.js +68 -0
  328. package/Resources/WebLibraries/three/addons/tsl/lighting/ClusteredLightsNode.js +994 -0
  329. package/Resources/WebLibraries/three/addons/tsl/lighting/DynamicLightsNode.js +201 -0
  330. package/Resources/WebLibraries/three/addons/tsl/lighting/LightProbeGridNode.js +183 -0
  331. package/Resources/WebLibraries/three/addons/tsl/lighting/data/AmbientLightDataNode.js +67 -0
  332. package/Resources/WebLibraries/three/addons/tsl/lighting/data/DirectionalLightDataNode.js +117 -0
  333. package/Resources/WebLibraries/three/addons/tsl/lighting/data/HemisphereLightDataNode.js +105 -0
  334. package/Resources/WebLibraries/three/addons/tsl/lighting/data/PointLightDataNode.js +140 -0
  335. package/Resources/WebLibraries/three/addons/tsl/lighting/data/SpotLightDataNode.js +167 -0
  336. package/Resources/WebLibraries/three/addons/tsl/math/Bayer.js +84 -0
  337. package/Resources/WebLibraries/three/addons/tsl/math/curlNoise.js +107 -0
  338. package/Resources/WebLibraries/three/addons/tsl/math/voronoiNoise.js +112 -0
  339. package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNode.js +542 -0
  340. package/Resources/WebLibraries/three/addons/tsl/shadows/TileShadowNodeHelper.js +212 -0
  341. package/Resources/WebLibraries/three/addons/tsl/utils/GroundedSkybox.js +62 -0
  342. package/Resources/WebLibraries/three/addons/tsl/utils/RNoise.js +51 -0
  343. package/Resources/WebLibraries/three/addons/tsl/utils/Raymarching.js +70 -0
  344. package/Resources/WebLibraries/three/addons/tsl/utils/SoftParticles.js +53 -0
  345. package/Resources/WebLibraries/three/addons/tsl/utils/SpecularHelpers.js +302 -0
  346. package/Resources/WebLibraries/three/addons/tsl/utils/TAAUtils.js +184 -0
  347. package/Resources/WebLibraries/three/addons/utils/BufferGeometryUtils.js +1523 -0
  348. package/Resources/WebLibraries/three/addons/utils/CameraUtils.js +82 -0
  349. package/Resources/WebLibraries/three/addons/utils/ColorUtils.js +76 -0
  350. package/Resources/WebLibraries/three/addons/utils/GaussianSplatUtils.js +229 -0
  351. package/Resources/WebLibraries/three/addons/utils/GeometryCompressionUtils.js +547 -0
  352. package/Resources/WebLibraries/three/addons/utils/GeometryUtils.js +226 -0
  353. package/Resources/WebLibraries/three/addons/utils/LDrawUtils.js +211 -0
  354. package/Resources/WebLibraries/three/addons/utils/SceneOptimizer.js +459 -0
  355. package/Resources/WebLibraries/three/addons/utils/SceneUtils.js +363 -0
  356. package/Resources/WebLibraries/three/addons/utils/ShadowMapViewer.js +244 -0
  357. package/Resources/WebLibraries/three/addons/utils/ShadowMapViewerGPU.js +233 -0
  358. package/Resources/WebLibraries/three/addons/utils/SkeletonUtils.js +496 -0
  359. package/Resources/WebLibraries/three/addons/utils/SortUtils.js +175 -0
  360. package/Resources/WebLibraries/three/addons/utils/UVsDebug.js +173 -0
  361. package/Resources/WebLibraries/three/addons/utils/WebGLTextureUtils.js +115 -0
  362. package/Resources/WebLibraries/three/addons/utils/WebGPUTextureUtils.js +81 -0
  363. package/Resources/WebLibraries/three/addons/utils/WorkerPool.js +167 -0
  364. package/Resources/WebLibraries/three/addons/utils/unwrapUVs.js +865 -0
  365. package/Resources/WebLibraries/three/three.core.js +61162 -0
  366. package/Resources/WebLibraries/three/three.module.js +19537 -0
  367. package/Resources/WebLibraries/three/three.tsl.js +41903 -0
  368. package/Resources/WebLibraries/three/three.webgpu.js +53714 -0
  369. package/Resources/skills/2d-game/SKILL.md +305 -0
  370. package/Resources/skills/3d-game/SKILL.md +274 -0
  371. package/Resources/skills/accounts/SKILL.md +41 -0
  372. package/Resources/skills/android-design/SKILL.md +159 -0
  373. package/Resources/skills/app-ai/SKILL.md +154 -0
  374. package/Resources/skills/app-intents/SKILL.md +31 -0
  375. package/Resources/skills/app-kinds/SKILL.md +122 -0
  376. package/Resources/skills/apple-watch/SKILL.md +43 -0
  377. package/Resources/skills/assets/SKILL.md +183 -0
  378. package/Resources/skills/building-blocks/SKILL.md +97 -0
  379. package/Resources/skills/device-control/SKILL.md +56 -0
  380. package/Resources/skills/device-integrations/SKILL.md +278 -0
  381. package/Resources/skills/finder-files/SKILL.md +19 -0
  382. package/Resources/skills/game/SKILL.md +414 -0
  383. package/Resources/skills/game-3d/SKILL.md +12 -0
  384. package/Resources/skills/game-art/SKILL.md +11 -0
  385. package/Resources/skills/game-feel/SKILL.md +13 -0
  386. package/Resources/skills/game-levels/SKILL.md +12 -0
  387. package/Resources/skills/game-live/SKILL.md +12 -0
  388. package/Resources/skills/game-physics/SKILL.md +13 -0
  389. package/Resources/skills/game-playtest/SKILL.md +26 -0
  390. package/Resources/skills/game-ui/SKILL.md +278 -0
  391. package/Resources/skills/github-projects/SKILL.md +59 -0
  392. package/Resources/skills/icloud-sync/SKILL.md +30 -0
  393. package/Resources/skills/iphone-hardware/SKILL.md +57 -0
  394. package/Resources/skills/iphone-widgets/SKILL.md +53 -0
  395. package/Resources/skills/lg-developer-mode/SKILL.md +152 -0
  396. package/Resources/skills/mac-widgets/SKILL.md +60 -0
  397. package/Resources/skills/maps/SKILL.md +8 -0
  398. package/Resources/skills/menu-bar/SKILL.md +36 -0
  399. package/Resources/skills/more-apps/SKILL.md +53 -0
  400. package/Resources/skills/phone-controllers/SKILL.md +79 -0
  401. package/Resources/skills/phone-pages/SKILL.md +173 -0
  402. package/Resources/skills/roku-developer-mode/SKILL.md +106 -0
  403. package/Resources/skills/scene-3d/SKILL.md +27 -0
  404. package/Resources/skills/scripting/SKILL.md +17 -0
  405. package/Resources/skills/share-extension/SKILL.md +22 -0
  406. package/Resources/skills/tv-design/SKILL.md +72 -0
  407. package/Resources/skills/web-app/SKILL.md +136 -0
  408. package/Resources/skills/web-game/SKILL.md +95 -0
  409. package/Resources/skills/web-or-native/SKILL.md +103 -0
  410. package/Resources/skills/wish-links/SKILL.md +156 -0
  411. package/THIRD_PARTY_NOTICES.md +170 -0
  412. package/cli/android.mjs +941 -0
  413. package/cli/browser.mjs +268 -0
  414. package/cli/calls.mjs +390 -0
  415. package/cli/dev.mjs +773 -0
  416. package/cli/devices.mjs +984 -0
  417. package/cli/lamp.mjs +1016 -0
  418. package/cli/lampapp.mjs +332 -0
  419. package/cli/lamps/android-host/LampPageGateway.kt +345 -0
  420. package/cli/lamps/android-host/app/build.gradle.kts +40 -0
  421. package/cli/lamps/android-host/build.gradle.kts +4 -0
  422. package/cli/lamps/android-host/game/AndroidManifest.xml +33 -0
  423. package/cli/lamps/android-host/game/MainActivity.kt +173 -0
  424. package/cli/lamps/android-host/gradle/libs.versions.toml +39 -0
  425. package/cli/lamps/android-host/gradle.properties +8 -0
  426. package/cli/lamps/android-host/page/AndroidManifest.xml +35 -0
  427. package/cli/lamps/android-host/page/MainActivity.kt +193 -0
  428. package/cli/lamps/android-host/settings.gradle.kts +30 -0
  429. package/cli/lamps/android-host/tools.json +43 -0
  430. package/cli/lamps/lamp-controllers.js +2 -0
  431. package/cli/lamps/lamp-for-games.js +6863 -0
  432. package/cli/lamps/lamp.js +7023 -0
  433. package/cli/lamps/mac-starter/.lamp/meta.json +1 -0
  434. package/cli/lamps/mac-starter/APP.md +12 -0
  435. package/cli/lamps/mac-starter/Package.swift +8 -0
  436. package/cli/lamps/mac-starter/Sources/App.swift +11 -0
  437. package/cli/lamps/mac-starter/Sources/ContentView.swift +17 -0
  438. package/cli/lamps/mac-starter/Sources/LampSupport.swift +18097 -0
  439. package/cli/lamps/mac-starter/build.sh +336 -0
  440. package/cli/lamps/mac-starter/gitignore +3 -0
  441. package/cli/lamps/mac-starter/lamp-starter.json +6 -0
  442. package/cli/lamps/web-starter/APP.md +8 -0
  443. package/cli/lamps/web-starter/app.js +1 -0
  444. package/cli/lamps/web-starter/index.html +17 -0
  445. package/cli/lamps/web-starter/lamp-starter.json +5 -0
  446. package/cli/lamps/web-starter/lamp.js +7023 -0
  447. package/cli/lamps/web-starter/style.css +25 -0
  448. package/cli/link.mjs +138 -0
  449. package/cli/mac.mjs +621 -0
  450. package/cli/mdns.mjs +205 -0
  451. package/cli/msix.mjs +413 -0
  452. package/cli/network.mjs +209 -0
  453. package/cli/outside.mjs +140 -0
  454. package/cli/page.js +165 -0
  455. package/cli/place.mjs +298 -0
  456. package/cli/png.mjs +184 -0
  457. package/cli/share.mjs +202 -0
  458. package/cli/skill/SKILL.md +255 -0
  459. package/cli/skills.mjs +71 -0
  460. package/cli/state.mjs +173 -0
  461. package/cli/update.mjs +57 -0
  462. package/package.json +20 -4
  463. package/site/lib/quota.js +59 -0
  464. package/site/lib/shared-wishes.js +996 -0
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: tv-design
3
+ description: Designing for a TV seen from across the room - type that reads at a distance, the edges a TV may cut off, contrast, focus that's unmistakable, layouts the remote's arrows move through the way they look, what to do instead of typing, glanceable pages, and motion a TV draws smoothly. For any app or game on a TV, web or native. Read before designing or restyling what a TV shows.
4
+ ---
5
+
6
+ # Designing for a TV
7
+
8
+ A TV is watched from a sofa three meters away, by people who aren't holding a mouse and may not be looking closely.
9
+ Whatever the app is (a game, a family calendar, a photo album, a scoreboard, a remote for something) and however it's
10
+ made, what the TV shows has to read at that distance and be driven with a few keys. Everything here is how to design
11
+ for that; the person's own direction wins over any of it. How a page or an app gets its keys, focus and size is the
12
+ technical guidance's (the TV rules, lamp.js's opening comment, the web-app skill, a native platform's own focus API):
13
+ this skill is about what to do with them.
14
+
15
+ ## Reading at a distance
16
+
17
+ - Text is large: about 28 px at 1080 lines tall as the smallest anything is (scale it with the screen's height, so
18
+ about 2.6% of it), headings much larger, and the one or two things that matter largest of all. Short lines; no
19
+ paragraphs to read.
20
+ - High contrast. A dark background is the default on a TV: it's kinder in a dim room and hides how a TV blooms bright
21
+ areas. Avoid pure white fills and thin light text on a light ground; avoid fine lines, small icons and detail that
22
+ depends on color alone.
23
+ - Keep everything that matters inside a margin of about 5% on every side: many TVs cut off their edges. Backgrounds and
24
+ pictures may run to the edge.
25
+ - Less on the screen than on a desktop: a TV shows a few big things, not a dense layout. Where there's a lot, show the
26
+ most important part and let the rest be one step away.
27
+
28
+ ## Glanceable pages
29
+
30
+ A page that's looked at rather than used (a dashboard, a calendar on the wall, a photo frame, a scoreboard, the day's
31
+ weather) reads at a glance: what matters first and largest, details smaller below, nothing that needs choosing to be
32
+ understood. It never scrolls as a whole; a long list scrolls inside its own box, or turns its own pages slowly. It
33
+ stays on for hours, so avoid anything that flashes, and let content move only when it changes (a slow fade between
34
+ photos, a number that updates in place).
35
+
36
+ ## The remote: focus
37
+
38
+ There's no pointer. The person moves focus with the arrows and presses OK, so:
39
+
40
+ - What has focus is unmistakable from across the room: a thick outline, or a scale and a glow, never just a slight
41
+ change of color. Exactly one thing has focus, and something always does when anything can be chosen; when a screen
42
+ opens, put focus on what the person most likely wants.
43
+ - Lay things out on a clear grid or in rows, so pressing an arrow moves focus where the eye expects. Avoid scattered
44
+ layouts where "down" is ambiguous.
45
+ - Targets are large and spaced apart; nothing depends on hover.
46
+ - Back always goes back one step, and from the first screen leaves the app. Don't trap the person anywhere without a
47
+ way out with Back.
48
+ - A dialog keeps focus inside itself until it's closed.
49
+
50
+ ## Typing
51
+
52
+ Typing with a remote is slow and tiring. Avoid text fields unless the app can't work without one: offer choices to
53
+ pick from, remember what was typed before, or let a phone do the typing (the phone-controllers and phone-pages skills).
54
+
55
+ ## Games on a TV
56
+
57
+ Everyone on the sofa sees the same screen: the score, lives and prompts are large and near the edges' safe margin,
58
+ not in small corners. Name the controls the way the controller in the players' hands names them. Pause on Back or the
59
+ menu button, with focus on Resume.
60
+
61
+ ## Motion and speed
62
+
63
+ A TV's browser and processor are far slower than a Mac's. Keep animations few, short and on `transform` and `opacity`
64
+ in a page; avoid large blurs, shadows over big areas and video behind text. Pictures no larger than they're shown.
65
+
66
+ ## Native apps on a TV
67
+
68
+ The same rules hold: Apple TV apps use the system's focus (focusable views, `.focusSection()` for rows) and its own
69
+ large type styles; an Android TV app uses Compose for TV's focusable cards and rows, keeps everything about 48 dp in
70
+ from the sides and 27 dp from the top and bottom, and body text at 16 sp and up with larger titles. Rows or a grid of
71
+ large cards suit a TV better than long lists. Let the platform draw focus where it does, and make sure your own views
72
+ show it as clearly.
@@ -0,0 +1,136 @@
1
+ ---
2
+ name: web-app
3
+ description: Apps made as a web page Lamp shows on each device - lamp.js's building blocks (AI, saved data, the app's files, the project's other apps), the remote's focus and keys, what the person's own things need from the app around the page, and what each device's browser runs. Read before writing or changing an app's page.
4
+ ---
5
+
6
+ # Web apps
7
+
8
+ A web app is one page (HTML, CSS and JavaScript in Web/) that Lamp shows on each device it's on. The same page, so
9
+ write it once for all of them and let each device's differences be handled where they are: lamp.js for what Lamp
10
+ gives every page, a few lines of your own where a device needs something else. How a game's page runs is the game
11
+ skill's; this one is about the page itself.
12
+
13
+ ## Lamp's building blocks: lamp.js
14
+
15
+ `Web/lamp.js` is Lamp's, written before every build; index.html loads it before the app's own scripts. Read its
16
+ opening comment for the whole list. What it gives:
17
+
18
+ - **LampAI**: text, pictures and quick judgments, answered by Lamp on the person's Mac with the AI they set up.
19
+ Every call is a Promise. Text from outside the app goes in `data`, never into the prompt. Where a feature depends
20
+ on it, check `LampAI.isAvailable('text')` and show a short note when it can't answer: away from the Mac's Wi‑Fi, or
21
+ with Lamp closed, it can't.
22
+ - **LampAI.act**: the person asks the app to do something in their own words, and the app's own reads and writes do
23
+ it; "Doing things for the person" below, with **LampVoice** and **LampAI.hear** for saying it.
24
+ - **LampStore**: what the app saves, as JSON on the device. Once something is saved, only ever add to it: a new field
25
+ gets a default where it's read, and a saved one is never renamed or retyped, because people rely on their data
26
+ through every change.
27
+ - **LampAssets**: the app's own files that come with it.
28
+ - **Lamp.wish**: the project's other apps (an iPhone, Mac or Android app beside the page), messages and shared values;
29
+ the wish-links skill says how they share data.
30
+ - **Lamp.controllers** and `Lamp.phonePage`: phones on the same Wi‑Fi as controllers or a second screen; the
31
+ phone-controllers skill first.
32
+
33
+ ## On the web, without Lamp
34
+
35
+ Putting it on GitHub (Also put on GitHub, on its link's card) gives a web app a page anyone opens in a browser, with no Lamp anywhere: the page as it is, with
36
+ lamp.js. There, `LampAI.isAvailable` answers false and its calls fail with a sentence saying the page is away from
37
+ Lamp, `LampNative.available` is false, and `Lamp.wish` can't reach the project's other apps; `LampStore` and `LampAssets`
38
+ work as they do everywhere. So every feature that leans on Lamp keeps the app usable without it: the app's own buttons
39
+ for everything AI would do, example content where the person's own things would be, and a short line where something
40
+ needs Lamp, never an error or an empty screen.
41
+
42
+ ## Doing things for the person
43
+
44
+ `LampAI.act(request, { about, context, tools, history, onStep })` runs a short loop: the AI picks calls among the
45
+ app's tools, the page runs them, the AI sees the results, until it replies (at most 4 AI calls and 6 writes a
46
+ turn, and 25 seconds over OpenRouter or a minute through Claude Code, Codex or a model on the Mac). It works with
47
+ whichever AI the person set up for apps' text, so don't tie it to voice: typing works wherever `act` does. Its comment in lamp.js has the shapes. This is the one recipe for it:
48
+
49
+ - Show the feature where `LampAI.isAvailable('act')` is true, and keep the app's own buttons for everything: it only
50
+ adds a way in. Where it's false, keep it visible with a short reason and a way to set it up in Lamp, and keep what
51
+ was typed; don't send it by itself once setup is done. Whether AI belongs in the app at all, and the contract to
52
+ write in APP.md, are the app-ai skill's.
53
+ - Tools are small reads and writes over the app's own data, ids in and ids out, never "do anything". A read has
54
+ `reads: true`; everything else is a write. Nothing destructive (a delete, a clear) without an Undo the person sees.
55
+ - Every write has a `check` that looks its item up again by id and says in a sentence why it can't be done (gone,
56
+ already done, in the past, nobody of that name); `run` changes the data the way the app's own button does, and
57
+ returns the item as it is after. Fencing outside text helps the AI read it, but the checks are what hold the line.
58
+ - Make the ids of what a write adds from `call.key`, or keep the key on the change, so the same request made again
59
+ finds it instead of adding a second.
60
+ - Say what happened from the result's `done`, `failed` and `skipped`, which are what the page ran, never from the AI's
61
+ `reply`; add the reply only when it asks something (`ask`) or nothing was changed.
62
+ - A question back may come with `choices` (two to four short answers): offer them as buttons with the first focused,
63
+ and take only the first answer, a button, what was heard or what was typed. With none, it's answered by voice or
64
+ typing; never guess choices from the question's wording.
65
+ - Keep what each write changed for Undo, and undo only what's still as the write left it; say which ones it left.
66
+ - Show each step while it runs (`onStep`), and cancel the turn (`turn.cancel()`) when the person closes it or the page
67
+ is hidden.
68
+ - `about` says what the app is and its rules for asking back: which person, which day and time, which of two things
69
+ that both fit.
70
+
71
+ Saying it instead of typing it: where the app around the page has a microphone (`LampVoice.status()`, which never
72
+ prompts: the Mac, iPhone and iPad, Android and Android TV, a TV remote's microphone included) and Lamp can transcribe
73
+ (`LampAI.isAvailable('hear')`), `LampVoice.listen({ session, onLevel })` records what's said and `LampAI.hear(audio)`
74
+ turns it into text for `act`. Their comments in lamp.js have the details. The recipe:
75
+
76
+ - One deliberate press starts listening (opening the app's Ask), never a key that means something else on the remote;
77
+ show the level as it's heard, a Stop that the opening press can't trigger, and "Type instead" wherever text can be
78
+ typed. Never hide a typed way in because there's no voice.
79
+ - Float Ask over the page rather than replacing it, and keep the remote in it while it's open (`Lamp.scope`, Tab on
80
+ the Mac, and arrows consumed at its edges), with something in it always focused, the one the person moved to kept
81
+ across changes; give focus back to where it was when it closes. A button newly
82
+ focused ignores OK for a moment, so a held press doesn't press it.
83
+ - Give every recording a session of the page's own, and cancel it (`LampVoice.cancel`) when the person closes or the
84
+ page hides; drop any recording, transcript or answer that comes back for a session that has ended, and a transcript
85
+ that comes back after the person has typed or talked again.
86
+ - Act only on `quiet` and `stopped`: `cap` may have cut the person off, so ask them to say it again shorter; say so
87
+ plainly for `nothing` and `denied`.
88
+ - Read the reply out with `LampVoice.speak`, and listen again for an answer only once it has finished, without moving
89
+ focus off the choices. Close by itself only after a finished answer read out to the end; any key, press or typing
90
+ calls that off, and never close over a draft, while a question waits or after a failure.
91
+
92
+ ## The person's own things
93
+
94
+ A page can't read the person's mail, calendar, contacts, photos or where they are. Where Lamp's app is around the page
95
+ (a Mac, an iPhone or iPad), that app can: register a call in Sources/Native.swift and ask for it from the page with
96
+ `LampNative.call(name, args)`. Elsewhere `LampNative.available` is false and the calls reject, so the page shows
97
+ example content then, never an error. When a web app that's to go on a TV, Android or the Xbox lives on the person's own
98
+ things, say what a page can't reach there; when it needs what only native code does, offer it native (the web-or-native
99
+ skill).
100
+
101
+ ## A remote: focus and keys
102
+
103
+ On a TV, and anywhere a page is driven by arrows and OK, there's no pointer. lamp.js moves focus with the arrows
104
+ between buttons, links, fields and anything marked `data-focus`, to the nearest in that direction, and OK clicks what
105
+ has it, so most apps need no key code of their own:
106
+
107
+ - give the first thing to focus with `Lamp.focus(...)` when a screen opens;
108
+ - Back goes back a screen with `Lamp.onBack(fn)` (return true when handled); unhandled on the first screen, it leaves
109
+ the app;
110
+ - other keys (play, pause, the color keys, numbers) come by name through `Lamp.onKey(fn)`;
111
+ - keep the arrows inside a dialog with `Lamp.scope` while it's open; a game takes them over with
112
+ `Lamp.navigation = false`.
113
+
114
+ On a phone or a Mac the same page is tapped or clicked, so a page that works with the remote works there too. How to
115
+ design for the remote and for a TV across the room (what focus looks like, layouts it moves through, typing) is the
116
+ tv-design skill's.
117
+
118
+ ## The browser a page meets
119
+
120
+ Which devices take a page is `make_app_for`'s table. Where one does, the page meets one of these engines:
121
+
122
+ | Device | What shows the page | Worth knowing |
123
+ |---|---|---|
124
+ | Mac, iPhone, iPad | Lamp's app around the page (WebKit) | Modern; LampNative reaches the person's things |
125
+ | Android phone or tablet | Lamp's app around the page (Android's WebView, Chromium) | Modern on recent devices |
126
+ | Samsung and LG TVs | The TV's own browser engine | Chromium 108 to 132 on recent models, older on older ones; WebGL 2 not on every Samsung |
127
+ | Android TV, Google TV, Fire TV | Lamp's app around the page (Android's WebView), on the TV's home screen | As on Android phones |
128
+ | Xbox | Lamp's web host (Edge WebView2) | Modern |
129
+
130
+ A TV keeps the page's syntax to what its older browsers run, as the TV rules say when the app is for one. Designing
131
+ what a TV shows, seen from across a room, is the tv-design skill's.
132
+
133
+ ## Speed
134
+
135
+ A TV or a cheap phone draws far less than a Mac. Keep animations few and on `transform` and `opacity`, lists that
136
+ scroll in their own box rather than the page, and pictures no larger than they're shown.
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: web-game
3
+ description: The short guide to a new web game at home on the Mac, on Lamp's game runtime - the runtime's contract, the stage in the window, screens over the canvas, keeping the player's place, how it looks, and what's checked when. Lamp hands it over with make_app_for, with game-feel and the skills the call's `needs` named; for this game they stand in for the game, game-ui, 2d-game and 3d-game skills, which serve games elsewhere.
4
+ ---
5
+
6
+ # A new web game on the Mac
7
+
8
+ This guide holds how the game runs on Lamp's runtime; game-feel, handed with it, holds what makes it good to play. Both are for every game, and with the skills `needs` named they're what you write it from: don't open the game, game-ui, 2d-game or 3d-game skills, or read Web/lamp-game.js or Web/lamp-phaser.js in full: grep them for one export when you need it. In 2D the game is Phaser 3.90 scenes through `phaser()`. In 3D, game-3d says how it draws; the rest here holds. Write the first files together in one message, then finish: Lamp builds the game and opens it when your turn ends.
9
+
10
+ ## The runtime's contract
11
+
12
+ - **Files.** Yours are `Web/index.html` (keep its head: lamp.js, the import map, then game.js as a module), `Web/game.js` and modules beside it; delete the scaffold's world.js and making.js with `delete_file` beside your writes. lamp-game.js, lamp-phaser.js, lamp-controllers.js, lamp.js, phaser/, three/, rapier/ and Sources/ are Lamp's: never edit them.
13
+ - **One frame clock.** Phaser's loop is asleep; each of the runtime's frames steps it once. Use a scene's `update(time, delta)` (milliseconds), tweens and Phaser's timers. Never requestAnimationFrame, setTimeout, setInterval, Date, Math.random or localStorage: `random()`, `save(name, value)`, `load(name)`, so the preview replays a play exactly.
14
+ - **Input.** `pad()` merges controllers, keys and touch: `lx ly rx ry` -1 to 1 (up positive), buttons as BUTTON bits in `down pressed released`. WASD and the arrows are the left stick, Space or Enter is A. Phaser's keyboard is off: never `addKey`. Name the controls once in CONTROLS; a prompt uses `label()` or `glyph()` inside `onInput(draw)`, never a key's name. Keys the person named: `keyboardHints: { leftStick: 'arrows' }`.
15
+ - **Sound.** Phaser's is off. Before writing any, `assets` with `kind` sound and `limit` 30 lists every effect: fetch one for each thing the player does or meets, and use the paths it gives. Load each once with `await sound.load('assets/…')` at the top of game.js and `sound.play(s, { volume })` when things happen; `sound.tone({…})` only for what nothing there fits.
16
+ - **Local files.** Nothing comes from the network. Pictures load in `preload`, or are drawn once with `this.make.graphics({ add: false })` and `generateTexture`.
17
+
18
+ ## The stage and the window
19
+
20
+ The 1920x1080 stage is fitted to the window with black around it, from 480x270 up. Lay everything out in stage units, with the player, HUD and every control inside it, 96 px in from the sides and 54 from top and bottom. Nothing scrolls or zooms, and nothing listens for resize. HTML sizes itself from the stage as `#ui` below does, never in fixed CSS pixels.
21
+
22
+ ## Screens over the canvas
23
+
24
+ The canvas is `position: fixed`, so anything without a stacking order of its own lies under it. Title, HUD and results live in one `#ui` box over the stage, above the canvas, passing clicks through except on buttons. Lamp's own layers start at z-index 10.
25
+
26
+ ```html
27
+ <style>
28
+ #ui { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); width: min(100vw, 177.78vh); aspect-ratio: 16 / 9;
29
+ z-index: 5; overflow: hidden; pointer-events: none; font-size: calc(min(100vw, 177.78vh) / 64); color: #fff; }
30
+ #ui button { pointer-events: auto; font: inherit; }
31
+ .hidden { display: none; }
32
+ </style>
33
+ <div id="ui"><div id="title"><h1>…</h1><button id="play">Play</button></div>
34
+ <div id="hud" class="hidden">…</div><div id="results" class="hidden">…<button id="again">Play Again</button></div></div>
35
+ ```
36
+
37
+ ```js
38
+ import * as Phaser from 'phaser';
39
+ import { phaser, pad } from './lamp-phaser.js';
40
+ import { BUTTON, STICK, sound, random, save, load, label, onInput, hot } from './lamp-game.js';
41
+
42
+ const CONTROLS = { move: STICK.LEFT, start: BUTTON.A, pause: BUTTON.MENU };
43
+ const play = hot(import.meta).state('play', { version: 1, start: () => ({ mode: 'title', score: 0, left: 30, x: 960 }) });
44
+ const catchSound = await sound.load('assets/pack/coin.wav'); // the page path `assets` gave
45
+ const el = id => document.getElementById(id);
46
+
47
+ class Main extends Phaser.Scene {
48
+ constructor() { super('main'); }
49
+ create() { // the one start: it reads the state and shows that screen
50
+ this.ship = this.physics.add.sprite(play.x, 940, 'ship').setCollideWorldBounds(true);
51
+ el('play').onclick = el('again').onclick = () => this.begin();
52
+ this.show();
53
+ }
54
+ begin() { Object.assign(play, { mode: 'play', score: 0, left: 30 }); this.show(); }
55
+ end() { play.mode = 'over'; save('best', Math.max(load('best') ?? 0, play.score)); this.show(); }
56
+ show() { for (const [id, mode] of [['title', 'title'], ['hud', 'play'], ['results', 'over']]) el(id).classList.toggle('hidden', play.mode !== mode); }
57
+ update(time, delta) {
58
+ const p = pad(), dt = delta / 1000;
59
+ if (play.mode !== 'play') { if (p.pressed & CONTROLS.start) this.begin(); this.ship.setVelocityX(0); return; }
60
+ this.ship.setVelocityX(p.lx * 900); play.x = this.ship.x;
61
+ if ((play.left -= dt) <= 0) this.end();
62
+ }
63
+ }
64
+ phaser({ scenes: [Main], physics: { default: 'arcade' }, busy: () => play.mode === 'play' });
65
+ ```
66
+
67
+ ## The flow
68
+
69
+ Title, play, results, unless the request plainly suits another opening; keep it in a `Flow:` line in APP.md. The title has the name and one big Play; a click or A starts it, and it names no key or control: those come after the press, briefly, as the round begins. The HUD stays large through play. Results say what happened first, then Play Again, which goes straight into a round. Play and Play Again are really in view and clickable.
70
+
71
+ ## Keeping the player's place
72
+
73
+ Changes go into the running game, and these rules keep the player's place through every one; game-live is for a change that moves the game's structure. Everything that says where the game is goes in the one `state` object, plain data: change its fields, never replace it. `create` reads it and builds that place, with no title over a game under way. HUD and menus are found at each start, never at a module's top level, and `busy()` is true while a round is on.
74
+
75
+ ## How it looks
76
+
77
+ Decide before drawing: its world, one material its screens are made of, four to eight colors, one signature motion. Compose each screen for this game, not a centered stack of pills, emoji art or soft cards on a gradient. Every action answers at once in sight and sound, each with a short effect from the `assets` tool. The finished look in game-feel is the bar every screen meets. The HTML above shows how screens layer over the canvas and follow the state, not a finished design: style it for this game, keeping the fixed stage and the black around it.
78
+
79
+ ## What's checked, and when
80
+
81
+ Lamp checks the game itself: its code parses, it builds, and it opens without crashing. A failure there comes back to you to fix, as another step. Lamp also tells the person whether its window drew. So write the change and finish, with no `look_at_app` or `use_app`, and nothing in the shell that plays, screenshots or runs the game in its place. Your last reply says in a sentence what you made; whether it's open and drew is Lamp's to say, after your reply, so never say it's built, open, working or tested.
82
+
83
+ When the person asks you to play it, test it, check it or judge how it looks, open the game-playtest skill and do only what they asked. One such request doesn't reach the changes after it.
84
+
85
+ ## More, when the game calls for it
86
+
87
+ What a game needs beyond this and game-feel follows from its mechanics and how it's drawn, not from the words of the request. The skills `make_app_for`'s `needs` named came with this guide; one the game turns out to need, now or in a later request, open with `read_skill` then. Most games need none.
88
+
89
+ - **game-3d**: it's drawn in 3D, a world with depth and a camera in it.
90
+ - **game-physics**: things move as bodies, falling, rolling, stacking, tilting, bouncing off each other. Steering, simple gravity and what touches what don't need it.
91
+ - **game-levels**: more than one level or stage, unlocks and a level select, a menu that's a place.
92
+ - **game-art**: the person asked for a look, or the game is mostly its look.
93
+ - **2d-game**: tilemaps, a scrolling world, sprite-sheet animation.
94
+ - **game-live**, never in `needs`: open it when a change to the open game moves its structure (new or split modules, a world that streams, what has to last renamed or moved) or won't go in. A color, a number or text needs only the rules above.
95
+ - **assets**: choosing between packs.
@@ -0,0 +1,103 @@
1
+ ---
2
+ name: web-or-native
3
+ description: Choosing how an app or game is made - as a web page Lamp's host shows on each device, or in the device's own code - from the default the table of devices gives (web wherever Lamp has a host for a page), the few things only native code does (a menu bar icon, widgets, Siri and Shortcuts, Health, share sheets), and on which devices, when to ask the person and what to tell them. Read before the first make_app_for of a project, and before changing how an app is made or adding a device.
4
+ ---
5
+
6
+ # Web or native
7
+
8
+ Every app and game Lamp makes is made one of two ways:
9
+
10
+ - **Web**: one page (HTML and JavaScript) that Lamp's host shows on each device, the same page everywhere it goes.
11
+ - **Native**: the device's own code. Swift for Apple's devices (one code for all of them), Kotlin for Android, and
12
+ what an integration declares for its device.
13
+
14
+ `make_app_for`'s description has the table of devices: what each one runs, and how a build gets onto it. It refuses
15
+ a make Lamp can't build on a device, with the reason, and the request's device line says what Lamp knows of the
16
+ person's own devices. Those are the facts, and the only place they're kept; this skill doesn't repeat them.
17
+
18
+ ## The default
19
+
20
+ A page is where every app and game starts. When the person names no make, an app or a game is **web** wherever Lamp
21
+ has a host for a page: a Mac, an iPhone or iPad, an Android phone or tablet, a Samsung or LG TV, an Android TV and an
22
+ Xbox. Where there's none (an Apple TV, an Apple Watch, a Roku), it's native. A game is on Lamp's game runtime (the game
23
+ skill says what it's drawn with). One app across several devices is web where every one of them takes a page.
24
+
25
+ A web app is one page that goes anywhere: the person can open it on another device later without it being written
26
+ again, and putting it on GitHub gives it a link anyone can open in a browser without Lamp. On a Mac, an iPhone or an iPad the app around the page still reaches
27
+ the person's mail, calendar, reminders, contacts, photos and location (`LampNative`, the web-app skill).
28
+
29
+ Make it **native** only when it needs something a page can't be:
30
+
31
+ - a Mac app that lives in the menu bar (the menu-bar skill), takes files from Finder (the finder-files skill), or is a
32
+ utility that works where the person already is or in the background (a global shortcut, the selection in another
33
+ app, opening at login: the app-kinds skill);
34
+ - widgets, Live Activities or Control Center controls (the mac-widgets and iphone-widgets skills), or an Apple Watch
35
+ app (the apple-watch skill);
36
+ - its actions in Siri, Shortcuts, Spotlight or the Action button (the app-intents skill), or a place in the share
37
+ sheet (the share-extension skill);
38
+ - Apple Health, iCloud sync, work while an iPhone app is closed, or the phone's hardware beyond what a page has (the
39
+ iphone-hardware and icloud-sync skills);
40
+ - 3D in Swift with RealityKit (the scene-3d skill), or a game inside an Apple thing (Game Center, a widget).
41
+
42
+ When one of these is part of what was asked, choose native and say why in a sentence. When the person asks for one
43
+ later in an app made web, say what it needs, and offer to make it native.
44
+
45
+ The default is where you start, not a limit:
46
+
47
+ - **A make the person names is theirs.** When they ask for a web app, or a native one, make it that way wherever Lamp
48
+ can build it; say in a sentence what that costs only when it matters.
49
+ - **Nothing switches silently.** Devices found on the network aren't a request for one app across them: add a device
50
+ only once the person has said that's what they want, or answered so when you asked.
51
+ - **An app the project has is never converted to follow the default.** It's for a new app, and for a change the person
52
+ asks for. An app made native before keeps its make.
53
+ - **Separate apps that talk don't need the same make.** The project's apps reach each other through `LampWish` on
54
+ whichever devices they're on, however each is made (the wish-links skill).
55
+ - **Never choose a make to get around a limit of Lamp's**: two apps of one code in one project, say (the more-apps
56
+ skill). Say what the limit is instead, and offer what can be done.
57
+ - **Never refuse a make that works only because it isn't the default.** Only the table, and the refusal it gives,
58
+ says what can't be built.
59
+
60
+ ## What to weigh
61
+
62
+ - **What the app needs from the device**: the list above. A page reaches the person's things only through Lamp's app
63
+ around it, where there is one (`LampNative`, the web-app skill): on a TV, Android or the Xbox it shows example content
64
+ instead. A game made native for an Apple thing is SpriteKit for 2D: say that it then stays on Apple's devices, where
65
+ a game on the runtime can go to Android, a TV, the Xbox or the web later without being written again.
66
+ - **How it gets to the people who use it.** Read the table's way onto each device, for each make. On some devices a
67
+ page still comes inside an app of Lamp's that is installed the same way a native app is.
68
+ - **Whose devices, and how many.** One person's own Mac or phone, a family's TV, every phone at a party: who has to
69
+ install or open what.
70
+ - **What it's played or used with.** A remote, a controller, touch, phones in the room: the game skill and the
71
+ phone-controllers skill say what each takes.
72
+
73
+ When the app needs several devices, it can be one app on all of them, or several of the project's apps, each made for its
74
+ device, that talk through `LampWish`. Adding one more app to a project that has one is the person's to choose: the
75
+ more-apps skill says how to ask.
76
+
77
+ ## When to ask
78
+
79
+ Only when the answer really changes what you'd make, and only in one line about people and devices, never in the
80
+ words "web" or "native": "Is this for your iPhone, or for everyone's phones at the party?" When the request already
81
+ says, or a wrong guess is cheap to change, choose, build, and say in a sentence what you chose and how it gets onto
82
+ their devices.
83
+
84
+ ## Saying how it gets there
85
+
86
+ Tell the person how the build reaches each device, as `make_app_for` answers it ("each phone is paired with this Mac",
87
+ "each phone joins the TV's game by a link"), so a choice that doesn't suit them shows at once.
88
+
89
+ ## Away from home
90
+
91
+ Each way of connecting has its own reach, said where it's described: phones joining a TV app's page do it on the same
92
+ Wi‑Fi with Lamp open on this Mac, and a game's on the Mac with Lamp open or closed (the phone-controllers skill); the project's own apps find each other on the home
93
+ network, and once Lamp has introduced them go on talking with Lamp closed (the wish-links skill, which also says what
94
+ reaching each other away from home takes). Lamp runs no relay of its own for players in other homes: when that's what
95
+ the person wants, say so plainly, and offer what works (playing on one Wi‑Fi, or another way of connecting, as the
96
+ wish-links skill says).
97
+
98
+ ## Changing it later
99
+
100
+ `make_app_for` with an app's folder in `app` changes how that app is made: it keeps its folder and what it saved, but
101
+ the new code doesn't read what the old one saved unless you write it to, and Lamp moves nothing across, so say so when
102
+ it matters. One more app beside the others is `another`, only once the person chose that when you asked (the
103
+ `more-apps` skill). `remove_app` takes one away, which the person can undo.
@@ -0,0 +1,156 @@
1
+ ---
2
+ name: wish-links
3
+ description: How the apps of a project, and one app open on several devices at once (two iPhones, a screen on an iPad and a TV), share data and send each other messages - Lamp's LampWish block and the shared collections built on it (LampStore.shared, LampStore.sharedFiles) for the same data on every device, what to do while another app of the project isn't made yet, and when another way fits better. Read before writing how they reach each other.
4
+ ---
5
+
6
+ # The apps of a project, talking to each other
7
+
8
+ A project of several apps (a Mac app and an Android app, a TV app and an iPhone app, a game and the phone app that
9
+ sends it things to play with, a screen on the wall and the app that fills it) usually needs them to share something:
10
+ a score, a list, a "next" button. So does one app open on several devices at once: the same app on two iPhones, or a
11
+ screen shown on the kitchen iPad and the TV. There's more than one way to do it. Lamp gives every app one way built
12
+ in, `LampWish`, and it's the one to use unless the wish or the person calls for another.
13
+
14
+ ## LampWish, built in
15
+
16
+ Every app of the project has it, the same in each language: `LampWish.shared` in LampSupport.swift, `LampWish` in
17
+ LampSupport.kt, `Lamp.wish` in lamp.js (a TV app's page, a game's and a screen's, in Web/lamp.js). Read the block's
18
+ own comment there before using it.
19
+
20
+ - Each app of the project is a peer named by its folder in the project, lowercased: "tv", "iphone", "apple" (an app for
21
+ iPhone and Mac), "mac", "android", "game", "screen".
22
+ - `peers` lists the project's other apps that are open now (observable: @Published, a StateFlow, onPeers).
23
+ - `peer("tv")` is that app, open or not, with its `status`: `state`, a `reason` in words to show as they are ("Open
24
+ the TV app on your TV.", "The TV app was last open 5 min ago. Open it on your TV.", "The TV app isn't ready yet."
25
+ for one Lamp hasn't made) and `lastSeen`. Every app the project asks for is there, even one not made yet. A reason
26
+ changes as time goes by: watch every app's (`apps`, observable as `peers` is; `onApps` in lamp.js), not only the open
27
+ ones.
28
+ - `send(data, to: "tv")` sends JSON of 16 KB at most to one of them, `send(data)` to all; false, with why in the app's
29
+ log, when it wasn't sent. `onMessage { from, data in … }` hears what they send. A message is for apps open now.
30
+ - `sendFile(data, name: "photo.jpg", type: "image/jpeg", to: "tv")` (`Lamp.wish.sendFile(data, 'iphone', { name,
31
+ type })` in lamp.js) sends a file of up to 64 MB to one app open now, two at a time to each; the transfer it gives
32
+ says how far it's got and why it failed, and can be cancelled. `onFile { from, file in … }` hears the files they send,
33
+ whole. Like a message, a file is for an app open now.
34
+ - `values` is a small map of JSON every app of the project keeps on its device (each value 8 KB at most, all of them
35
+ 64 KB). `set("list", value)` sets one here and in the others, at once if they're open or when they next meet; nil
36
+ (null) removes it. `onChange { key, value, from in … }` hears every change, this app's own included. Where two apps
37
+ set one while apart, the later setting wins in both.
38
+ - `LampStore.shared` and `LampStore.sharedFiles` (below) keep lists and files the same on every copy of the app.
39
+ - The app's own `status` says how its link stands, with a `reason` when something keeps it from the others (on a Mac
40
+ or iPhone, `localNetworkDenied`: the person turned off Local Network for it). An open app built by an earlier Lamp is
41
+ `outOfDate`: still open, with a reason saying to open it from Lamp. More states may come: treat any you don't name as
42
+ not connected.
43
+ - An app can be open on several devices at once (a screen on the kitchen iPad, the TV and a photo frame, the same app
44
+ on two iPhones), in a project of one app as in a project of several: each is a copy of it, and every copy reaches the others and keeps the same `values`. `peer("screen").copies` lists where it's
45
+ open now (`id`, `device`, `since`); another copy of this same app shows in `peers` while it's open. A message to an app
46
+ goes to every copy of it; a file goes to one copy, the one opened last unless `to` names a copy's `id`. The third
47
+ argument of `onMessage` (`copy`) and `file.copy` say which copy sent it, to answer that one alone. Put what every
48
+ screen shows in `values`, so a copy opened later catches up by itself. An app with no other app in its project is
49
+ `alone` until another copy of it opens; its copies first meet through Lamp on the Mac, and after that also reach
50
+ each other straight with Lamp closed.
51
+ - Where a copy can't reach the others, `Lamp.wish` is `away`, with a reason saying so. Write the sharing the same way
52
+ for every place, and keep the game or screen whole without it.
53
+ - A Roku app (an app for a device through its integration) can't reach the others yet, nor they it: it's not in the
54
+ room's list, so the others don't see it at all, and its own `LampWish` (LampWish.brs) is always `away`. Don't write
55
+ the others to wait for it or send it anything; each keeps what it shows its own. An app on the Mac or an iPhone can
56
+ still steer it as a remote with `LampRoku` (keys, opening it by launching "dev"), which needs no link.
57
+ - `LampWishStatus()` (SwiftUI, Compose) and `Lamp.wish.statusView()` (lamp.js) show all of that ready-made, a line
58
+ for each other app, or one app's line with its peer name. Use them, restyle them, or show the statuses your own way.
59
+
60
+ ## The same data on every device: shared collections
61
+
62
+ When one app is open on several devices (a screen on the Mac, the kitchen iPad, the TV and an Android photo frame) and
63
+ each should show the same shopping list, chores, calendar or photos, keep that data in a **shared collection**, not
64
+ in `values`:
65
+
66
+ - `LampStore.shared("groceries", of: Grocery.self)` in Swift (an ObservableObject: `items`, `put`, `get`, `delete`,
67
+ `publish`, `onChange { id, item, from in }`), `LampStore.shared<Grocery>("groceries") { it.id }` in Kotlin (`items`
68
+ is a StateFlow), `LampStore.shared('groceries')` in lamp.js (items are objects with an `id`; `all()`, `put`, `get`,
69
+ `delete`, `publish`, `onChange(fn(id, item, from))`). Each copy keeps the items on its device and works alone; copies
70
+ merge them item by item whenever they meet, through Lamp or straight on the home network with Lamp closed. While Lamp
71
+ runs on the Mac it keeps every shared collection too, so a copy that opens when no other is open still gets the
72
+ latest, and what it changes then reaches the others when they open. Lamp is never one of the copies or apps. Two copies
73
+ that changed different items while apart both keep both; where two changed the same item, the later change wins in
74
+ both; a deleted item stays deleted. An item is at most 8 KB as JSON, everything the app shares at most 1 MB
75
+ (thousands of small items).
76
+ - Give each item a stable id of its own (a UUID made when it's added, or the id of what it stands for, such as a
77
+ calendar event's), and keep things that change apart in separate items: a list's items, not the list as one.
78
+ - `publish(items)`, for what one copy can read and the others can't (the Mac's or the iPad's calendars, through
79
+ `LampNative` on a screen or a game): this copy's items become exactly these; unchanged ones cost nothing, and items
80
+ other copies put are left alone. Publish again each time it's read.
81
+ - `LampStore.sharedFiles("photos")`: files kept on every copy (`put(name, data, type)`, `get(name)`, `url(name)`,
82
+ `files`/`all()` with whether each is here yet, `delete`, `onChange`). A copy that can read the album puts each
83
+ picture; every other copy fetches the bytes from a copy that has them or from Lamp, including copies that open later. 64 MB a
84
+ file, 256 MB in all. On a TV the bytes are kept in memory and fetched again each time the app opens.
85
+ - Draw from the collection and redraw on `onChange`; never keep a copy of your own. Never split a list into `values`
86
+ by hand, or send the same data around with messages to keep copies in step.
87
+ - A shared collection is the app's own, the same on all its copies, unless it's the **project's own**: with
88
+ `wish: true` (`LampStore.shared("events", of: Event.self, wish: true)` in Swift,
89
+ `LampStore.shared<Event>("events", wish = true) { it.id }` in Kotlin, `LampStore.shared('events', { wish: true })`
90
+ in lamp.js, and `sharedFiles(name, wish: true)` likewise) every app of the project keeps it the same: a Mac app and the
91
+ iPhone app beside it sharing one calendar, a TV game and the phone controllers sharing a scoreboard. Every app that
92
+ uses it gives the same name. It merges as above; each app's 1 MB counts only the items it set last.
93
+ Use the project's own collection whenever different apps of the project show the same records; never make one app the
94
+ keeper of them for the others, since that app is often closed or asleep.
95
+ - A collection starts empty: the project's own and the app's own of the same name are separate, so switching a list to
96
+ `wish: true` doesn't bring its items along. When the person already has items there, copy them over.
97
+ - Apps that share a collection agree on what an item looks like: the same fields with the same meaning. Add a field
98
+ as optional, so an app that doesn't know it yet still reads the item, and change every app that uses the collection
99
+ together.
100
+
101
+ What it gives: the apps find each other on the home Wi‑Fi with nothing to sign up for, pair, host or pay for. While
102
+ Lamp is open on the Mac it introduces them; with Lamp closed, the Mac asleep or Lamp updating they go on talking
103
+ straight to each other on the same network. What they say is sealed with a key only the project's apps have, and none of
104
+ it leaves the home network. What it doesn't do: reach an app on another network (a phone away from home), keep a
105
+ message or a file for an app that isn't open, or hold more than a small amount in `values`.
106
+
107
+ How to use it well:
108
+ - Start it as each app opens.
109
+ - Pick by what the data is. Something that happens now (a button pressed, "next round") is a message. A list or
110
+ records every copy of this app shows (groceries, chores, events, photos) is a shared collection, and the project's own
111
+ (`wish: true`) when the project's other apps show them too. Something another
112
+ app of the project should still see after being closed (a score, a setting, what's on the dashboard) fits `values`:
113
+ they catch up by themselves when they meet, so there's nothing to resend. Something big the other app should have
114
+ (a photo, a recording, a document, a game to play) is a file: send it when that app is open, show its progress, and
115
+ say so plainly when it fails. The app's own records belong in its own store (LampStore), with only what the other app
116
+ needs to show put in `values`.
117
+ - Draw from `values` and redraw on `onChange`, rather than keeping a copy of your own that can drift. What an app kept
118
+ on its device can reach `values` a moment after it opens (on a TV, once it knows its project), so never set a default
119
+ because `values` looks empty at launch: show an empty state, and set a value when the person does something.
120
+ - Keep values to a few names you reuse. Each name counts at least 32 bytes against the 64 KB, and a removed one keeps
121
+ counting for a month, so values aren't a queue of ever-new names: keep such records in the app's own store.
122
+ - Several apps may change the same value while apart, and the later setting wins whole. Where both sides add to one
123
+ list, use a shared collection: the app's own between its copies, the project's own (`wish: true`) between different
124
+ apps, so neither undoes the other's.
125
+ - Watch `peers` as it changes (onChange of it, collecting the StateFlow, onPeers), not by looking now and then: an app
126
+ closed and opened again quickly leaves and comes back between two looks.
127
+ - Where something needs another app, show why it isn't there with its `reason` (or the status view), and keep every
128
+ control usable while it isn't open.
129
+ - Never build a server, sockets, polling or pairing of your own beside it, and never put the app's token or Lamp's
130
+ addresses in the code.
131
+
132
+ ## While another app of the project isn't made yet
133
+
134
+ A project can ask for an app this Mac can't build yet (Google's tools aren't set up, Xcode is missing). Lamp says which
135
+ at the end of the request and makes it as soon as it can. The app you're building already has `LampWish`, and the
136
+ missing one is in its list, not open. So:
137
+ - Write the sharing with `LampWish` now, as if the other app were there. When it's made it has the same block, and the
138
+ two find each other with nothing more to do.
139
+ - Until then show its `reason` where it matters, and make this app whole and useful on its own.
140
+ - Don't stand in for the missing app with an online service, or leave the sharing out "for later".
141
+
142
+ ## When another way fits
143
+
144
+ `LampWish` is the default, not the only way. Use another when:
145
+ - **The person asks for one**: Tailscale, ntfy, their own server or database, a service they already pay for. Do it
146
+ their way.
147
+ - **The apps must reach each other away from home**, not just on the same Wi‑Fi. For the Mac and the iPhone of one
148
+ person, iCloud (the icloud-sync skill) keeps their data the same anywhere. Anything else is a service outside the
149
+ home: ask first, with one `ask`, when it needs an account, costs money or sends the person's data off their network,
150
+ and say what that means in plain words.
151
+ - **Both are needed**: `LampWish` at home for what's instant, and a service or iCloud for what must reach a device
152
+ away.
153
+
154
+ A public relay such as an ntfy.sh topic is readable by anyone who guesses the topic's name: don't send anything
155
+ personal through one in the clear, and tell the person. Whatever way you choose, keep it in one place in each app's
156
+ code, so it can be changed later without touching the rest.