astro-tractstack 2.0.0-rc.0 → 2.0.0-rc.10
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.
- package/README.md +275 -26
- package/bin/create-tractstack.js +173 -40
- package/dist/index.js +14 -6
- package/package.json +4 -4
- package/templates/brand/og.png +0 -0
- package/templates/brand/oglogo.png +0 -0
- package/templates/css/frontend.css +1 -3519
- package/templates/src/client/{analytics-events.ts → analytics-events.js} +16 -22
- package/templates/src/client/{belief-events.ts → belief-events.js} +15 -29
- package/templates/src/client/{sse.ts → sse.js} +20 -74
- package/templates/src/components/Footer.astro +6 -2
- package/templates/src/components/Header.astro +8 -7
- package/templates/src/components/codehooks/SankeyDiagram.tsx +4 -3
- package/templates/src/components/edit/PanelSwitch.tsx +3 -8
- package/templates/src/components/edit/pane/AddPanePanel_new.tsx +1 -1
- package/templates/src/components/storykeep/Dashboard_Advanced.tsx +1 -1
- package/templates/src/components/storykeep/Dashboard_Branding.tsx +1 -1
- package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +1 -1
- package/templates/src/components/storykeep/controls/content/KnownResourceForm.tsx +1 -1
- package/templates/src/components/storykeep/controls/content/MenuForm.tsx +1 -1
- package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +1 -1
- package/templates/src/components/tenant/RegistrationForm.tsx +5 -3
- package/templates/src/constants.ts +0 -2
- package/templates/src/layouts/Layout.astro +7 -7
- package/templates/src/pages/[...slug]/edit.astro +8 -1
- package/templates/src/pages/[...slug].astro +1 -1
- package/templates/src/pages/api/tailwind.ts +5 -21
- package/templates/src/pages/context/[...contextSlug]/edit.astro +8 -1
- package/templates/src/pages/context/[...contextSlug].astro +1 -1
- package/templates/src/pages/storykeep/advanced.astro +1 -1
- package/templates/src/pages/storykeep/branding.astro +1 -1
- package/templates/src/pages/storykeep/content.astro +1 -1
- package/templates/src/pages/storykeep/profile.astro +1 -1
- package/templates/src/utils/compositor/templateMarkdownStyles.ts +8 -0
- package/templates/src/utils/helpers.ts +1 -0
- package/utils/inject-files.ts +14 -6
package/README.md
CHANGED
|
@@ -1,56 +1,305 @@
|
|
|
1
|
-
#
|
|
1
|
+
# TractStack v2
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Redeeming the web from boring experiences**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
no-code community engine
|
|
5
|
+
Free web press by [At Risk Media](https://atriskmedia.com)
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
## Epistemic Hypermedia Server
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
TractStack is a new species of web platform that makes it possible for millions of websites to adapt to each visitor instead of showing everyone the same thing. It's an **adaptive website builder** that creates fast, beautiful, SEO-ready, and accessible websites that respond intelligently to user behavior.
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
Built on [Astro](https://astro.build/) with [HTMX](https://htmx.org/) and a [Golang](https://go.dev/) backend, TractStack uses SQLite by default with optional [Turso](https://app.turso.tech/) cloud database support.
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
## Key Features
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
- **Adaptive Content**: Websites that dynamically respond to visitor behavior
|
|
16
|
+
- **Multi-tenant Architecture**: Host multiple sites from a single installation
|
|
17
|
+
- **Built-in CMS**: StoryKeep content management system
|
|
18
|
+
- **Real-time Updates**: Server-sent events and HTMX for dynamic interactions
|
|
19
|
+
- **Production Ready**: SSL certificates, nginx integration, systemd services
|
|
20
|
+
- **Zero Config Database**: Works out of the box with SQLite3
|
|
17
21
|
|
|
18
|
-
|
|
22
|
+
## Quick Install
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
### One-Line Installer
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
```bash
|
|
27
|
+
curl -fsSL https://get.tractstack.com | bash
|
|
28
|
+
```
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
This automatically installs both the Go backend and creates a new Astro project with TractStack integration.
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
### Installation Options
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
- `--quick` - Development setup in user directory (no sudo required)
|
|
35
|
+
- `--prod --domain=yourdomain.com` - Production single-tenant
|
|
36
|
+
- `--multi --domain=yourdomain.com` - Production multi-tenant hosting
|
|
37
|
+
- `--dedicated SITE_ID --domain=yourdomain.com` - Isolated dedicated instance
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
## Manual Installation
|
|
40
|
+
|
|
41
|
+
**Prerequisites:**
|
|
42
|
+
|
|
43
|
+
- Node.js 20+
|
|
44
|
+
- pnpm (recommended) or npm
|
|
45
|
+
- Go 1.22+
|
|
46
|
+
- Git
|
|
47
|
+
|
|
48
|
+
### Step 1: Install Go Backend
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
mkdir -p ~/t8k/src
|
|
52
|
+
cd ~/t8k/src
|
|
33
53
|
git clone https://github.com/AtRiskMedia/tractstack-go.git
|
|
34
54
|
cd tractstack-go
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
echo "GO_BACKEND_PATH=$HOME/t8k/t8k-go-server/" > .env
|
|
56
|
+
echo "GIN_MODE=release" >> .env
|
|
57
|
+
go build -o tractstack-go ./cmd/tractstack-go
|
|
37
58
|
```
|
|
38
59
|
|
|
39
|
-
|
|
60
|
+
### Step 2: Create Astro Frontend
|
|
40
61
|
|
|
41
|
-
```
|
|
42
|
-
cd ~/
|
|
62
|
+
```bash
|
|
63
|
+
cd ~/t8k
|
|
43
64
|
pnpm create astro@latest my-tractstack --template minimal --typescript strict --install
|
|
44
65
|
cd my-tractstack
|
|
45
66
|
pnpm add astro-tractstack@latest
|
|
67
|
+
echo "PRIVATE_GO_BACKEND_PATH=$HOME/t8k/t8k-go-server/" > .env
|
|
46
68
|
npx create-tractstack
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Step 3: Start Development
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Terminal 1: Go backend
|
|
75
|
+
cd ~/t8k/src/tractstack-go
|
|
76
|
+
./tractstack-go
|
|
77
|
+
|
|
78
|
+
# Terminal 2: Astro frontend
|
|
79
|
+
cd ~/t8k/src/my-tractstack
|
|
47
80
|
pnpm dev
|
|
48
81
|
```
|
|
49
82
|
|
|
50
|
-
|
|
83
|
+
Visit https://127.0.0.1:4321 to access your site and activate your Story Keep (CMS).
|
|
84
|
+
|
|
85
|
+
## Installation Types
|
|
86
|
+
|
|
87
|
+
### Development (Quick Install)
|
|
88
|
+
|
|
89
|
+
- Local setup in `~/t8k/`
|
|
90
|
+
- No sudo required
|
|
91
|
+
- Perfect for development and testing
|
|
92
|
+
- SQLite database included
|
|
93
|
+
|
|
94
|
+
### Production Single-Tenant
|
|
95
|
+
|
|
96
|
+
- System-wide installation at `/home/t8k/`
|
|
97
|
+
- SSL certificates via Let's Encrypt
|
|
98
|
+
- nginx reverse proxy
|
|
99
|
+
- systemd services for automatic startup
|
|
100
|
+
- PM2 process management
|
|
101
|
+
|
|
102
|
+
### Production Multi-Tenant
|
|
103
|
+
|
|
104
|
+
- Same as single-tenant plus:
|
|
105
|
+
- Wildcard domain support (`*.yourdomain.com`)
|
|
106
|
+
- Tenant management at `/sandbox/register`
|
|
107
|
+
- Multiple isolated websites from one installation
|
|
108
|
+
|
|
109
|
+
### Dedicated Instance
|
|
110
|
+
|
|
111
|
+
- Completely separate installation per site
|
|
112
|
+
- Own source code, binaries, and data
|
|
113
|
+
- Maximum isolation and customization
|
|
114
|
+
- Perfect for agencies managing multiple clients
|
|
115
|
+
|
|
116
|
+
## Project Structure
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
~/t8k/ # Development install
|
|
120
|
+
├── src/
|
|
121
|
+
│ ├── tractstack-go/ # Go backend source
|
|
122
|
+
│ │ └── tractstack-go # Compiled binary
|
|
123
|
+
│ └── my-tractstack/ # Astro frontend
|
|
124
|
+
│ ├── src/
|
|
125
|
+
│ │ ├── components/ # Custom components
|
|
126
|
+
│ │ ├── pages/ # Astro pages
|
|
127
|
+
│ │ └── custom/ # Your customizations
|
|
128
|
+
│ └── astro.config.mjs
|
|
129
|
+
└── t8k-go-server/ # Backend data storage
|
|
130
|
+
├── config/
|
|
131
|
+
│ ├── t8k/
|
|
132
|
+
│ │ └── tenants.json # Tenant registry
|
|
133
|
+
│ └── default/ # Default tenant config
|
|
134
|
+
│ ├── env.json # Core configuration
|
|
135
|
+
│ ├── brand.json # Site branding
|
|
136
|
+
│ ├── knownResources.json # Resource tracking
|
|
137
|
+
│ ├── tailwindWhitelist.json # CSS optimization
|
|
138
|
+
│ └── media/ # Media files
|
|
139
|
+
│ ├── images/
|
|
140
|
+
│ └── css/
|
|
141
|
+
├── db/
|
|
142
|
+
│ └── default/
|
|
143
|
+
│ └── tractstack.db # SQLite database
|
|
144
|
+
└── log/
|
|
145
|
+
├── system.log
|
|
146
|
+
├── tenant.log
|
|
147
|
+
└── database.log
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Production Structure
|
|
151
|
+
|
|
152
|
+
Production installations live at `/home/t8k/` with the same structure plus:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
/home/t8k/
|
|
156
|
+
├── bin/
|
|
157
|
+
│ └── tractstack-go # Production binary
|
|
158
|
+
├── etc/
|
|
159
|
+
│ ├── letsencrypt/ # SSL certificates
|
|
160
|
+
│ ├── pm2/ # PM2 configs
|
|
161
|
+
│ └── t8k-ports.conf # Port allocations
|
|
162
|
+
├── scripts/
|
|
163
|
+
│ └── t8k-concierge.sh # Build automation
|
|
164
|
+
└── state/ # Build queue
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Multi-Tenant Features
|
|
168
|
+
|
|
169
|
+
TractStack v2 includes powerful multi-tenant capabilities:
|
|
170
|
+
|
|
171
|
+
- **Tenant Registration**: Self-service tenant creation at `/sandbox/register`
|
|
172
|
+
- **Domain Routing**: Automatic subdomain routing (`tenant.yourdomain.com`)
|
|
173
|
+
- **Isolated Data**: Each tenant has separate databases and media
|
|
174
|
+
- **Capacity Management**: Configurable tenant limits
|
|
175
|
+
- **Email Activation**: Automated tenant activation emails
|
|
176
|
+
|
|
177
|
+
## SSL Certificate Management
|
|
178
|
+
|
|
179
|
+
### Cloudflare DNS (Automated)
|
|
180
|
+
|
|
181
|
+
Create `/root/.secrets/certbot/cloudflare.ini`:
|
|
182
|
+
|
|
183
|
+
```ini
|
|
184
|
+
dns_cloudflare_api_token = YOUR_API_TOKEN_HERE
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Certificates are obtained automatically during installation.
|
|
51
188
|
|
|
52
|
-
|
|
189
|
+
### Manual DNS Verification
|
|
190
|
+
|
|
191
|
+
Without Cloudflare, the installer guides you through manual DNS TXT record verification.
|
|
192
|
+
|
|
193
|
+
## Service Management
|
|
194
|
+
|
|
195
|
+
### Main Installation
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Status
|
|
199
|
+
sudo systemctl status tractstack-go
|
|
200
|
+
sudo -u t8k pm2 status astro-main
|
|
201
|
+
|
|
202
|
+
# Restart
|
|
203
|
+
sudo systemctl restart tractstack-go
|
|
204
|
+
sudo -u t8k pm2 restart astro-main
|
|
205
|
+
|
|
206
|
+
# Logs
|
|
207
|
+
sudo journalctl -u tractstack-go -f
|
|
208
|
+
sudo -u t8k pm2 logs astro-main
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Dedicated Instances
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# Replace SITE_ID with your site identifier
|
|
215
|
+
sudo systemctl status tractstack-go@SITE_ID
|
|
216
|
+
sudo -u t8k pm2 status astro-SITE_ID
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Build System
|
|
220
|
+
|
|
221
|
+
The build concierge processes automated builds via CSV files in `/home/t8k/state/`:
|
|
222
|
+
|
|
223
|
+
```csv
|
|
224
|
+
type=main,tenant=default,command=build
|
|
225
|
+
type=dedicated,site=SITE_ID,command=build
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The system automatically:
|
|
229
|
+
|
|
230
|
+
1. Pulls latest code from Git
|
|
231
|
+
2. Builds Go backend and Astro frontend
|
|
232
|
+
3. Extracts Tailwind CSS optimizations
|
|
233
|
+
4. Restarts services
|
|
234
|
+
5. Cleans up processed files
|
|
235
|
+
|
|
236
|
+
## Database Options
|
|
237
|
+
|
|
238
|
+
### SQLite (Default)
|
|
239
|
+
|
|
240
|
+
- Zero configuration required
|
|
241
|
+
- Perfect for most websites
|
|
242
|
+
- Automatic backups and maintenance
|
|
243
|
+
- Scales to hundreds of thousands of visitors
|
|
244
|
+
|
|
245
|
+
### Turso Cloud Database
|
|
246
|
+
|
|
247
|
+
- Distributed SQLite with global replication
|
|
248
|
+
- Configure during site initialization
|
|
249
|
+
- Seamless scaling for high-traffic sites
|
|
250
|
+
- Built-in analytics and monitoring
|
|
251
|
+
|
|
252
|
+
## Development Workflow
|
|
253
|
+
|
|
254
|
+
1. **Edit Content**: Use StoryKeep CMS at `/storykeep`
|
|
255
|
+
2. **Customize Design**: Modify components in `src/custom/`
|
|
256
|
+
3. **Add Features**: Create CodeHooks for dynamic functionality
|
|
257
|
+
4. **Test Changes**: Hot reloading with `pnpm dev`
|
|
258
|
+
5. **Deploy**: Automated builds handle production updates
|
|
259
|
+
|
|
260
|
+
## API Integration
|
|
261
|
+
|
|
262
|
+
TractStack provides RESTful APIs for:
|
|
263
|
+
|
|
264
|
+
- Content management
|
|
265
|
+
- User analytics
|
|
266
|
+
- Belief tracking (visitor preferences)
|
|
267
|
+
- Multi-tenant operations
|
|
268
|
+
- Media handling
|
|
269
|
+
|
|
270
|
+
## Uninstalling
|
|
271
|
+
|
|
272
|
+
**For Production installations**, the uninstall script is located at `/home/t8k/scripts/`:
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
sudo /home/t8k/scripts/t8k-uninstall.sh
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**For Quick install (development)**, the script is in:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
sudo ~/t8k/src/tractstack-go/pkg/scripts/t8k-uninstall.sh
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Support & Documentation
|
|
285
|
+
|
|
286
|
+
- **Documentation**: https://tractstack.org
|
|
287
|
+
- **GitHub Issues**: https://github.com/AtRiskMedia/tractstack-go/issues
|
|
288
|
+
- **Email Support**: hello@tractstack.com
|
|
289
|
+
- **Community**: Join discussions about adaptive web experiences
|
|
53
290
|
|
|
54
291
|
## License
|
|
55
292
|
|
|
56
|
-
Functional Source License
|
|
293
|
+
**Functional Source License (FSL)** - Commercial use encouraged!
|
|
294
|
+
|
|
295
|
+
The only restriction is no re-selling TractStack as-a-service. Perfect for:
|
|
296
|
+
|
|
297
|
+
- Agency client projects
|
|
298
|
+
- Corporate websites
|
|
299
|
+
- Personal projects
|
|
300
|
+
- Open source contributions
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
_TractStack v2 - Making the web adaptive, one site at a time_
|
|
305
|
+
_Made with ❤️ by [At Risk Media](https://atriskmedia.com)_
|
package/bin/create-tractstack.js
CHANGED
|
@@ -28,6 +28,72 @@ function detectPackageManager() {
|
|
|
28
28
|
return 'pnpm';
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// Parse existing .env file
|
|
32
|
+
function getEnvState() {
|
|
33
|
+
const defaults = {
|
|
34
|
+
goBackend: 'http://localhost:8080',
|
|
35
|
+
tenantId: 'default',
|
|
36
|
+
goBackendPath: `${homedir()}/t8k-go-server/`,
|
|
37
|
+
enableMultiTenant: false,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const found = {
|
|
41
|
+
goBackend: false,
|
|
42
|
+
tenantId: false,
|
|
43
|
+
goBackendPath: false,
|
|
44
|
+
enableMultiTenant: false,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (!existsSync('.env')) {
|
|
48
|
+
return { envDefaults: defaults, envState: found };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const envContent = readFileSync('.env', 'utf-8');
|
|
53
|
+
const envVars = {};
|
|
54
|
+
|
|
55
|
+
envContent.split('\n').forEach((line) => {
|
|
56
|
+
line = line.trim();
|
|
57
|
+
if (line && !line.startsWith('#')) {
|
|
58
|
+
const [key, ...valueParts] = line.split('=');
|
|
59
|
+
if (key && valueParts.length > 0) {
|
|
60
|
+
let value = valueParts.join('=').trim();
|
|
61
|
+
if (
|
|
62
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
63
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
64
|
+
) {
|
|
65
|
+
value = value.slice(1, -1);
|
|
66
|
+
}
|
|
67
|
+
envVars[key.trim()] = value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
envDefaults: {
|
|
74
|
+
goBackend: envVars.PUBLIC_GO_BACKEND || defaults.goBackend,
|
|
75
|
+
tenantId: envVars.PUBLIC_TENANTID || defaults.tenantId,
|
|
76
|
+
goBackendPath:
|
|
77
|
+
envVars.PRIVATE_GO_BACKEND_PATH || defaults.goBackendPath,
|
|
78
|
+
enableMultiTenant:
|
|
79
|
+
envVars.PUBLIC_ENABLE_MULTI_TENANT === 'true' ||
|
|
80
|
+
defaults.enableMultiTenant,
|
|
81
|
+
},
|
|
82
|
+
envState: {
|
|
83
|
+
goBackend: !!envVars.PUBLIC_GO_BACKEND,
|
|
84
|
+
tenantId: !!envVars.PUBLIC_TENANTID,
|
|
85
|
+
goBackendPath: !!envVars.PRIVATE_GO_BACKEND_PATH,
|
|
86
|
+
enableMultiTenant: envVars.PUBLIC_ENABLE_MULTI_TENANT !== undefined,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.log(
|
|
91
|
+
kleur.yellow('⚠️ Found .env file but could not parse it, using defaults')
|
|
92
|
+
);
|
|
93
|
+
return { envDefaults: defaults, envState: found };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
31
97
|
async function main() {
|
|
32
98
|
// ASCII art
|
|
33
99
|
console.log(
|
|
@@ -89,13 +155,27 @@ ${kleur.bold('Examples:')}
|
|
|
89
155
|
process.exit(1);
|
|
90
156
|
}
|
|
91
157
|
|
|
92
|
-
//
|
|
93
|
-
const
|
|
94
|
-
|
|
158
|
+
// Parse existing .env values
|
|
159
|
+
const { envDefaults, envState } = getEnvState();
|
|
160
|
+
const hasExistingEnv = existsSync('.env');
|
|
161
|
+
|
|
162
|
+
if (hasExistingEnv) {
|
|
163
|
+
console.log(
|
|
164
|
+
kleur.yellow(
|
|
165
|
+
'📁 Found existing .env file, using current values as defaults\n'
|
|
166
|
+
)
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Build prompts array conditionally - only prompt for values not in .env
|
|
171
|
+
const promptQuestions = [];
|
|
172
|
+
|
|
173
|
+
if (!envState.goBackend) {
|
|
174
|
+
promptQuestions.push({
|
|
95
175
|
type: 'text',
|
|
96
176
|
name: 'goBackend',
|
|
97
177
|
message: 'TractStack Go backend URL:',
|
|
98
|
-
initial:
|
|
178
|
+
initial: envDefaults.goBackend,
|
|
99
179
|
validate: (value) => {
|
|
100
180
|
try {
|
|
101
181
|
new URL(value);
|
|
@@ -104,57 +184,117 @@ ${kleur.bold('Examples:')}
|
|
|
104
184
|
return 'Please enter a valid URL';
|
|
105
185
|
}
|
|
106
186
|
},
|
|
107
|
-
}
|
|
108
|
-
|
|
187
|
+
});
|
|
188
|
+
} else {
|
|
189
|
+
console.log(
|
|
190
|
+
kleur.green(`✓ Using Go backend URL: ${envDefaults.goBackend}`)
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!envState.enableMultiTenant && !enableMultiTenant) {
|
|
195
|
+
promptQuestions.push({
|
|
196
|
+
type: 'confirm',
|
|
197
|
+
name: 'enableMultiTenant',
|
|
198
|
+
message: 'Enable multi-tenant functionality?',
|
|
199
|
+
initial: enableMultiTenant || envDefaults.enableMultiTenant,
|
|
200
|
+
});
|
|
201
|
+
} else {
|
|
202
|
+
const willEnable = enableMultiTenant || envDefaults.enableMultiTenant;
|
|
203
|
+
console.log(
|
|
204
|
+
kleur.green(
|
|
205
|
+
`✓ Multi-tenant functionality: ${willEnable ? 'enabled' : 'disabled'}`
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Only prompt for tenantId if multi-tenant will be enabled and tenantId not in .env
|
|
211
|
+
const willEnableMultiTenant =
|
|
212
|
+
enableMultiTenant || envDefaults.enableMultiTenant;
|
|
213
|
+
if (willEnableMultiTenant && !envState.tenantId) {
|
|
214
|
+
promptQuestions.push({
|
|
109
215
|
type: 'text',
|
|
110
216
|
name: 'tenantId',
|
|
111
217
|
message: 'Tenant ID:',
|
|
112
|
-
initial:
|
|
218
|
+
initial: envDefaults.tenantId,
|
|
113
219
|
validate: (value) => value.length > 0 || 'Tenant ID is required',
|
|
114
|
-
}
|
|
115
|
-
|
|
220
|
+
});
|
|
221
|
+
} else if (willEnableMultiTenant) {
|
|
222
|
+
console.log(kleur.green(`✓ Using Tenant ID: ${envDefaults.tenantId}`));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!envState.goBackendPath) {
|
|
226
|
+
promptQuestions.push({
|
|
116
227
|
type: 'text',
|
|
117
228
|
name: 'goBackendPath',
|
|
118
229
|
message: 'TractStack Go backend path:',
|
|
119
|
-
initial:
|
|
230
|
+
initial: envDefaults.goBackendPath,
|
|
120
231
|
validate: (value) => {
|
|
121
232
|
if (!value || value.trim().length === 0) {
|
|
122
233
|
return 'Backend path is required';
|
|
123
234
|
}
|
|
124
|
-
// Ensure it ends with trailing slash for consistency
|
|
125
235
|
return true;
|
|
126
236
|
},
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
initial: includeExamples,
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
type: 'confirm',
|
|
137
|
-
name: 'enableMultiTenant',
|
|
138
|
-
message: 'Enable multi-tenant functionality?',
|
|
139
|
-
initial: enableMultiTenant,
|
|
140
|
-
},
|
|
141
|
-
]);
|
|
237
|
+
});
|
|
238
|
+
} else {
|
|
239
|
+
console.log(
|
|
240
|
+
kleur.green(`✓ Using Go backend path: ${envDefaults.goBackendPath}`)
|
|
241
|
+
);
|
|
242
|
+
}
|
|
142
243
|
|
|
143
|
-
|
|
144
|
-
|
|
244
|
+
// Always ask about examples (not stored in .env)
|
|
245
|
+
promptQuestions.push({
|
|
246
|
+
type: 'confirm',
|
|
247
|
+
name: 'includeExamples',
|
|
248
|
+
message:
|
|
249
|
+
'Include CodeHook examples? (custom components, collections route)',
|
|
250
|
+
initial: includeExamples,
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Run prompts only if there are questions
|
|
254
|
+
const responses =
|
|
255
|
+
promptQuestions.length > 0 ? await prompts(promptQuestions) : {};
|
|
256
|
+
|
|
257
|
+
// Merge responses with env defaults for final values
|
|
258
|
+
const finalResponses = {
|
|
259
|
+
goBackend: responses.goBackend || envDefaults.goBackend,
|
|
260
|
+
enableMultiTenant:
|
|
261
|
+
responses.enableMultiTenant ??
|
|
262
|
+
(enableMultiTenant || envDefaults.enableMultiTenant),
|
|
263
|
+
tenantId: responses.tenantId || envDefaults.tenantId,
|
|
264
|
+
goBackendPath: responses.goBackendPath || envDefaults.goBackendPath,
|
|
265
|
+
includeExamples: responses.includeExamples ?? includeExamples,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
if (!finalResponses.goBackend) {
|
|
269
|
+
console.log(kleur.red('\n✗ Setup cancelled.'));
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Use existing tenantId if multi-tenant is disabled
|
|
274
|
+
const finalTenantId = finalResponses.enableMultiTenant
|
|
275
|
+
? finalResponses.tenantId
|
|
276
|
+
: envDefaults.tenantId;
|
|
277
|
+
|
|
278
|
+
if (!finalTenantId) {
|
|
279
|
+
console.log(kleur.red('\n✗ Setup cancelled - Tenant ID is required.'));
|
|
145
280
|
process.exit(1);
|
|
146
281
|
}
|
|
147
282
|
|
|
148
283
|
// Create .env file
|
|
149
284
|
const envContent = `# TractStack Configuration
|
|
150
|
-
PUBLIC_GO_BACKEND="${
|
|
151
|
-
PUBLIC_TENANTID="${
|
|
152
|
-
PRIVATE_GO_BACKEND_PATH="${
|
|
285
|
+
PUBLIC_GO_BACKEND="${finalResponses.goBackend}"
|
|
286
|
+
PUBLIC_TENANTID="${finalTenantId}"
|
|
287
|
+
PRIVATE_GO_BACKEND_PATH="${finalResponses.goBackendPath.endsWith('/') ? finalResponses.goBackendPath : finalResponses.goBackendPath + '/'}"
|
|
288
|
+
PUBLIC_ENABLE_MULTI_TENANT="${finalResponses.enableMultiTenant ? 'true' : 'false'}"
|
|
153
289
|
`;
|
|
154
290
|
|
|
155
291
|
try {
|
|
156
292
|
writeFileSync('.env', envContent);
|
|
157
|
-
|
|
293
|
+
if (hasExistingEnv) {
|
|
294
|
+
console.log(kleur.green('✅ Updated .env file with new configuration'));
|
|
295
|
+
} else {
|
|
296
|
+
console.log(kleur.green('✅ Created .env file'));
|
|
297
|
+
}
|
|
158
298
|
} catch (error) {
|
|
159
299
|
console.log(kleur.red('❌ Failed to create .env file:', error.message));
|
|
160
300
|
process.exit(1);
|
|
@@ -453,17 +593,10 @@ export default defineConfig({
|
|
|
453
593
|
const runCommand =
|
|
454
594
|
packageManager === 'pnpm' ? 'pnpm run' : `${packageManager} run`;
|
|
455
595
|
|
|
456
|
-
console.log('\nNext steps:');
|
|
457
|
-
console.log(kleur.cyan('1. Start your Go backend:'));
|
|
458
|
-
console.log(' tractstack-go');
|
|
459
|
-
console.log(kleur.cyan('2. Start your Astro development server:'));
|
|
460
|
-
console.log(` ${runCommand} dev`);
|
|
461
|
-
|
|
462
596
|
if (responses.enableMultiTenant) {
|
|
463
597
|
console.log('\n' + kleur.bold('Multi-tenant features enabled:'));
|
|
464
598
|
console.log(` • Tenant registration: ${kleur.cyan('/sandbox/register')}`);
|
|
465
599
|
console.log(` • Subdomain routing middleware added`);
|
|
466
|
-
console.log(` • Admin-only tenant management`);
|
|
467
600
|
console.log(
|
|
468
601
|
`\n${kleur.yellow('Note:')} Make sure your Go backend has ENABLE_MULTI_TENANT=true`
|
|
469
602
|
);
|
|
@@ -477,7 +610,7 @@ export default defineConfig({
|
|
|
477
610
|
console.log(` • Custom components and CodeHooks`);
|
|
478
611
|
}
|
|
479
612
|
|
|
480
|
-
console.log('\n📚 Documentation: https://tractstack.org
|
|
613
|
+
console.log('\n📚 Documentation: https://tractstack.org');
|
|
481
614
|
}
|
|
482
615
|
|
|
483
616
|
main().catch(console.error);
|
package/dist/index.js
CHANGED
|
@@ -1245,16 +1245,16 @@ async function w(t, e, c) {
|
|
|
1245
1245
|
},
|
|
1246
1246
|
// Client Scripts
|
|
1247
1247
|
{
|
|
1248
|
-
src: t("../templates/src/client/sse.
|
|
1249
|
-
dest: "
|
|
1248
|
+
src: t("../templates/src/client/sse.js"),
|
|
1249
|
+
dest: "public/client/sse.js"
|
|
1250
1250
|
},
|
|
1251
1251
|
{
|
|
1252
|
-
src: t("../templates/src/client/belief-events.
|
|
1253
|
-
dest: "
|
|
1252
|
+
src: t("../templates/src/client/belief-events.js"),
|
|
1253
|
+
dest: "public/client/belief-events.js"
|
|
1254
1254
|
},
|
|
1255
1255
|
{
|
|
1256
|
-
src: t("../templates/src/client/analytics-events.
|
|
1257
|
-
dest: "
|
|
1256
|
+
src: t("../templates/src/client/analytics-events.js"),
|
|
1257
|
+
dest: "public/client/analytics-events.js"
|
|
1258
1258
|
},
|
|
1259
1259
|
// StoryKeep Editor (add new section)
|
|
1260
1260
|
{
|
|
@@ -1499,6 +1499,14 @@ async function w(t, e, c) {
|
|
|
1499
1499
|
src: t("../templates/brand/static.jpg"),
|
|
1500
1500
|
dest: "public/static.jpg"
|
|
1501
1501
|
},
|
|
1502
|
+
{
|
|
1503
|
+
src: t("../templates/brand/og.png"),
|
|
1504
|
+
dest: "public/brand/og.png"
|
|
1505
|
+
},
|
|
1506
|
+
{
|
|
1507
|
+
src: t("../templates/brand/oglogo.png"),
|
|
1508
|
+
dest: "public/brand/oglogo.png"
|
|
1509
|
+
},
|
|
1502
1510
|
{
|
|
1503
1511
|
src: t("../templates/brand/favicon.ico"),
|
|
1504
1512
|
dest: "public/brand/favicon.ico"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-tractstack",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
4
|
-
"description": "Astro integration for TractStack -
|
|
3
|
+
"version": "2.0.0-rc.10",
|
|
4
|
+
"description": "Astro integration for TractStack - redeeming the web from boring experiences",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"README.md"
|
|
19
19
|
],
|
|
20
20
|
"bin": {
|
|
21
|
-
"create-tractstack": "
|
|
21
|
+
"create-tractstack": "bin/create-tractstack.js"
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "vite build && tsc -p tsconfig.dts.json",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"license": "FSL-1.1-MIT",
|
|
38
38
|
"repository": {
|
|
39
39
|
"type": "git",
|
|
40
|
-
"url": "https://github.com/AtRiskMedia/astro-tractstack.git"
|
|
40
|
+
"url": "git+https://github.com/AtRiskMedia/astro-tractstack.git"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public",
|
|
Binary file
|
|
Binary file
|