Monorepo for Aesthetic.Computer
aesthetic.computer
1# Scripts Architecture
2
3## ✅ Final Organization (November 2024)
4
5After investigating script placement and dependency resolution, we arrived at this clean architecture:
6
7### Location: `scripts/` (workspace root)
8
9**Why root level?**
10- Logical separation: deployment code in `system/`, operational tools in `scripts/`
11- Clear organization: not buried in implementation directories
12- Consistent with existing `at/scripts/` pattern
13
14### Dependency Strategy: Shared Dependencies
15
16**Problem**: Scripts need packages like `@atproto/api`, `mongodb`, etc. that are installed in `system/node_modules/`
17
18**Solution**: Install same packages at root level
19- Added to root `package.json` dependencies
20- Small duplication (fine architecturally)
21- Node.js walks up from `scripts/atproto/` → `scripts/` → root → finds `node_modules/`
22- Same packages in `system/` for Netlify functions (they need bundled deps)
23
24**Dependencies shared**:
25```json
26{
27 "@atproto/api": "^0.17.2",
28 "@aws-sdk/client-s3": "^3.896.0",
29 "mongodb": "^6.20.0",
30 "dotenv": "^16.4.7",
31 "node-fetch": "^3.3.2"
32}
33```
34
35### Import Paths
36
37Scripts use relative paths to access backend modules:
38
39```javascript
40// From scripts/atproto/*.mjs
41import { connect } from "../../system/backend/database.mjs";
42import { createMediaRecord } from "../../system/backend/media-atproto.mjs";
43
44// From scripts/recovery/*.mjs
45import { connect } from "../../system/backend/database.mjs";
46import { userIDFromHandle } from "../../system/backend/authorization.mjs";
47```
48
49**Path breakdown**: `../../system/backend/`
50- `../` - up from `scripts/atproto/` to `scripts/`
51- `../` - up from `scripts/` to workspace root
52- `system/backend/` - into backend module directory
53
54### Environment Variables
55
56Scripts load `.env` from `system/.env`:
57
58```javascript
59import { config } from 'dotenv';
60config({ path: './system/.env' }); // Relative to workspace root
61```
62
63**Must run from workspace root** so `./system/.env` resolves correctly.
64
65## 🏗️ Directory Structure
66
67```
68/workspaces/aesthetic-computer/
69├── scripts/ # Operational scripts (NEW!)
70│ ├── README.md # Omakase menu for LLM
71│ ├── SETUP.md # Setup instructions
72│ ├── ARCHITECTURE.md # This file
73│ ├── atproto/ # ATProto sync/backfill tools
74│ │ ├── sync-atproto.mjs
75│ │ ├── backfill-kidlisp-rkeys.mjs
76│ │ └── ...
77│ └── recovery/ # Data recovery tools
78│ ├── recover-deleted-tapes.mjs
79│ └── check-tape-zips-in-spaces.mjs
80│
81├── system/ # Deployment code
82│ ├── backend/ # Reusable modules
83│ │ ├── database.mjs
84│ │ ├── media-atproto.mjs
85│ │ ├── authorization.mjs
86│ │ └── ...
87│ ├── netlify/
88│ │ └── functions/ # Netlify edge functions
89│ ├── .env # Secrets (in .gitignore)
90│ ├── node_modules/ # System dependencies
91│ └── package.json
92│
93├── at/scripts/atproto/ # External AT Protocol tools
94│ └── ... # Federation, lexicon publishing, etc.
95│
96├── node_modules/ # Root dependencies (includes script deps)
97└── package.json # Root packages (includes script deps)
98```
99
100## 🎯 Design Principles
101
1021. **Separation of Concerns**
103 - `system/` = deployment infrastructure (Netlify functions, edge compute)
104 - `scripts/` = operational tools (maintenance, sync, recovery)
105 - `at/scripts/` = external protocol tools (federation with other PDS)
106
1072. **Shared Dependencies**
108 - Accept small duplication for cleaner architecture
109 - Root level for scripts, system level for functions
110 - Both can use same versions (kept in sync)
111
1123. **Backend Modules as Library**
113 - `system/backend/*.mjs` = reusable utilities
114 - Used by: Netlify functions, operational scripts, AT tools
115 - Never create duplicate implementations
116
1174. **LLM-Friendly Documentation**
118 - `README.md` = "Omakase menu" of available scripts
119 - `SETUP.md` = Getting started, troubleshooting
120 - `ARCHITECTURE.md` = Design decisions (this file)
121
122## 🚀 Usage Pattern
123
124```bash
125# 1. Ensure dependencies installed
126npm install # (at root)
127
128# 2. Ensure secrets available
129ls system/.env # or copy from vault
130
131# 3. Run scripts from root
132node scripts/atproto/sync-atproto.mjs live --kidlisp-only
133node scripts/recovery/check-tape-zips-in-spaces.mjs @jeffrey
134```
135
136## 🔄 Alternatives Considered
137
138### ❌ Keep in `system/backend/`
139- **Pros**: Natural access to system/node_modules
140- **Cons**: Mixed with library code, unclear which are operations vs utilities
141
142### ❌ Move to `system/scripts/`
143- **Pros**: Still in system where deps are
144- **Cons**: Scripts aren't really "system" deployment code
145
146### ❌ Use NODE_PATH hack
147- **Pros**: Scripts could stay anywhere
148- **Cons**: Hacky, requires wrapper scripts, confusing
149
150### ✅ Root `scripts/` + shared deps (CHOSEN)
151- **Pros**: Clean separation, logical organization, minimal duplication
152- **Cons**: Some deps duplicated (acceptable tradeoff)
153
154## 📝 Commit Strategy
155
156Group related changes:
1571. Script organization (moves, README, SETUP)
1582. Dependency sharing (package.json updates)
1593. Netlify config fixes (@atproto/api externals)
160
161Message:
162```
163Organize operational scripts with shared dependencies
164
165- Move provisional scripts from system/backend/ to scripts/
166- Add atproto/ (sync/backfill) and recovery/ subdirectories
167- Share dependencies: install @atproto/api, mongodb, etc. at root
168- Fix netlify.toml: add @atproto/api to 4 function externals
169- Add documentation: README (omakase menu), SETUP, ARCHITECTURE
170
171All kidlisp/tapes/moods synced to ATProto successfully
172```