app-platform: remove unsupported saleor release surface
This commit is contained in:
parent
de60f7e21e
commit
f818f1dcc1
@ -64,32 +64,6 @@
|
|||||||
"bitcoin-knots"
|
"bitcoin-knots"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "saleor",
|
|
||||||
"title": "Saleor",
|
|
||||||
"version": "3.23",
|
|
||||||
"description": "Composable commerce platform with customer storefront, GraphQL API, dashboard, worker, mail testing, and tracing.",
|
|
||||||
"icon": "/assets/img/app-icons/saleor.svg",
|
|
||||||
"author": "Saleor",
|
|
||||||
"category": "commerce",
|
|
||||||
"tier": "recommended",
|
|
||||||
"dockerImage": "ghcr.io/saleor/saleor:3.23",
|
|
||||||
"repoUrl": "https://github.com/saleor/saleor",
|
|
||||||
"containerConfig": {
|
|
||||||
"ports": [
|
|
||||||
"9011:80",
|
|
||||||
"9010:80",
|
|
||||||
"8000:8000",
|
|
||||||
"8025:8025",
|
|
||||||
"16686:16686"
|
|
||||||
],
|
|
||||||
"volumes": [
|
|
||||||
"/var/lib/archipelago/saleor:/app/media",
|
|
||||||
"/var/lib/archipelago/saleor-db:/var/lib/postgresql/data"
|
|
||||||
],
|
|
||||||
"notes": "Installed as a Saleor stack: customer storefront on 9011, admin dashboard on 9010, API on 8000, Mailpit on 8025, and Jaeger on 16686. Supporting containers include PostgreSQL, Valkey, Celery worker, and services required by Saleor."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "mempool",
|
"id": "mempool",
|
||||||
"title": "Mempool Explorer",
|
"title": "Mempool Explorer",
|
||||||
|
|||||||
@ -171,12 +171,6 @@ fn image_var_for_app(app_id: &str) -> Option<&'static str> {
|
|||||||
"netbird" => Some("NETBIRD_DASHBOARD_IMAGE"),
|
"netbird" => Some("NETBIRD_DASHBOARD_IMAGE"),
|
||||||
"netbird-dashboard" => Some("NETBIRD_DASHBOARD_IMAGE"),
|
"netbird-dashboard" => Some("NETBIRD_DASHBOARD_IMAGE"),
|
||||||
"netbird-server" => Some("NETBIRD_SERVER_IMAGE"),
|
"netbird-server" => Some("NETBIRD_SERVER_IMAGE"),
|
||||||
"saleor" => Some("SALEOR_DASHBOARD_IMAGE"),
|
|
||||||
"saleor-api" | "saleor-worker" => Some("SALEOR_API_IMAGE"),
|
|
||||||
"saleor-db" => Some("SALEOR_POSTGRES_IMAGE"),
|
|
||||||
"saleor-cache" => Some("SALEOR_VALKEY_IMAGE"),
|
|
||||||
"saleor-jaeger" => Some("SALEOR_JAEGER_IMAGE"),
|
|
||||||
"saleor-mailpit" => Some("SALEOR_MAILPIT_IMAGE"),
|
|
||||||
|
|
||||||
// Fedimint
|
// Fedimint
|
||||||
"fedimint" | "fedimintd" => Some("FEDIMINT_IMAGE"),
|
"fedimint" | "fedimintd" => Some("FEDIMINT_IMAGE"),
|
||||||
@ -317,15 +311,6 @@ pub fn containers_for_stack(app_id: &str) -> Vec<(&'static str, &'static str)> {
|
|||||||
("netbird-dashboard", "NETBIRD_DASHBOARD_IMAGE"),
|
("netbird-dashboard", "NETBIRD_DASHBOARD_IMAGE"),
|
||||||
("netbird-server", "NETBIRD_SERVER_IMAGE"),
|
("netbird-server", "NETBIRD_SERVER_IMAGE"),
|
||||||
],
|
],
|
||||||
"saleor" => vec![
|
|
||||||
("saleor-db", "SALEOR_POSTGRES_IMAGE"),
|
|
||||||
("saleor-cache", "SALEOR_VALKEY_IMAGE"),
|
|
||||||
("saleor-api", "SALEOR_API_IMAGE"),
|
|
||||||
("saleor-worker", "SALEOR_API_IMAGE"),
|
|
||||||
("saleor-jaeger", "SALEOR_JAEGER_IMAGE"),
|
|
||||||
("saleor-mailpit", "SALEOR_MAILPIT_IMAGE"),
|
|
||||||
("saleor", "SALEOR_DASHBOARD_IMAGE"),
|
|
||||||
],
|
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -549,15 +549,6 @@ fn should_auto_start_stopped_container(name: &str, include_stack_members: bool)
|
|||||||
| "netbird-server"
|
| "netbird-server"
|
||||||
| "netbird-dashboard"
|
| "netbird-dashboard"
|
||||||
| "netbird"
|
| "netbird"
|
||||||
| "saleor-db"
|
|
||||||
| "saleor-cache"
|
|
||||||
| "saleor-jaeger"
|
|
||||||
| "saleor-mailpit"
|
|
||||||
| "saleor-api"
|
|
||||||
| "saleor-worker"
|
|
||||||
| "saleor"
|
|
||||||
| "saleor-storefront"
|
|
||||||
| "saleor-storefront-app"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,32 +602,6 @@ fn stack_recovery_specs() -> &'static [StackRecoverySpec] {
|
|||||||
],
|
],
|
||||||
containers: &["netbird-server", "netbird-dashboard", "netbird"],
|
containers: &["netbird-server", "netbird-dashboard", "netbird"],
|
||||||
},
|
},
|
||||||
StackRecoverySpec {
|
|
||||||
name: "saleor",
|
|
||||||
network: "saleor-net",
|
|
||||||
aliases: &[
|
|
||||||
("saleor-db", "db"),
|
|
||||||
("saleor-cache", "cache"),
|
|
||||||
("saleor-jaeger", "jaeger"),
|
|
||||||
("saleor-mailpit", "mailpit"),
|
|
||||||
("saleor-api", "api"),
|
|
||||||
("saleor-worker", "worker"),
|
|
||||||
("saleor", "saleor"),
|
|
||||||
("saleor-storefront", "storefront"),
|
|
||||||
("saleor-storefront-app", "storefront-app"),
|
|
||||||
],
|
|
||||||
containers: &[
|
|
||||||
"saleor-db",
|
|
||||||
"saleor-cache",
|
|
||||||
"saleor-jaeger",
|
|
||||||
"saleor-mailpit",
|
|
||||||
"saleor-api",
|
|
||||||
"saleor-worker",
|
|
||||||
"saleor",
|
|
||||||
"saleor-storefront",
|
|
||||||
"saleor-storefront-app",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,7 @@ The remaining migration work is mostly orchestration quality: post-reboot adopti
|
|||||||
Use a StartOS-inspired package model with Umbrel-like app folders.
|
Use a StartOS-inspired package model with Umbrel-like app folders.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
apps/saleor/
|
apps/example-commerce/
|
||||||
manifest.yml
|
manifest.yml
|
||||||
Dockerfile
|
Dockerfile
|
||||||
icon.svg
|
icon.svg
|
||||||
@ -109,12 +109,12 @@ Example `manifest.yml`:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
app:
|
app:
|
||||||
id: saleor
|
id: example-commerce
|
||||||
name: Saleor
|
name: Example Commerce
|
||||||
version: 3.23.0
|
version: 3.23.0
|
||||||
description: Composable commerce platform
|
description: Composable commerce platform
|
||||||
container:
|
container:
|
||||||
image: docker.io/myorg/saleor:3.23.0
|
image: docker.io/myorg/example-commerce:1.0.0
|
||||||
pull_policy: if-not-present
|
pull_policy: if-not-present
|
||||||
network: archy-net
|
network: archy-net
|
||||||
entrypoint: ["sh", "-lc"]
|
entrypoint: ["sh", "-lc"]
|
||||||
@ -125,7 +125,7 @@ app:
|
|||||||
template: https://{{HOST_MDNS}}:9010
|
template: https://{{HOST_MDNS}}:9010
|
||||||
secret_env:
|
secret_env:
|
||||||
- key: SALEOR_SECRET_KEY
|
- key: SALEOR_SECRET_KEY
|
||||||
secret_file: saleor-secret-key
|
secret_file: example-commerce-secret-key
|
||||||
dependencies:
|
dependencies:
|
||||||
- storage: 20Gi
|
- storage: 20Gi
|
||||||
resources:
|
resources:
|
||||||
@ -142,7 +142,7 @@ app:
|
|||||||
protocol: tcp
|
protocol: tcp
|
||||||
volumes:
|
volumes:
|
||||||
- type: bind
|
- type: bind
|
||||||
source: /var/lib/archipelago/saleor
|
source: /var/lib/archipelago/example-commerce
|
||||||
target: /data
|
target: /data
|
||||||
options: [rw]
|
options: [rw]
|
||||||
environment:
|
environment:
|
||||||
@ -293,7 +293,6 @@ Then moderate apps:
|
|||||||
|
|
||||||
Then complex apps:
|
Then complex apps:
|
||||||
|
|
||||||
- Saleor
|
|
||||||
- Mempool
|
- Mempool
|
||||||
- BTCPay Server
|
- BTCPay Server
|
||||||
- NetBird only if safe
|
- NetBird only if safe
|
||||||
@ -307,9 +306,11 @@ Leave for later:
|
|||||||
- System update
|
- System update
|
||||||
- Mesh/Web5/FIPS core services
|
- Mesh/Web5/FIPS core services
|
||||||
|
|
||||||
## Saleor Reference Goal
|
## Complex Stack Reference Goal
|
||||||
|
|
||||||
Saleor should become the showcase package. It should prove:
|
Saleor has been removed from the supported release catalog until it has a real
|
||||||
|
manifest-owned package. A future complex stack should become the showcase
|
||||||
|
package and prove:
|
||||||
|
|
||||||
- Multi-container stack support.
|
- Multi-container stack support.
|
||||||
- Generated secrets.
|
- Generated secrets.
|
||||||
@ -322,7 +323,7 @@ Saleor should become the showcase package. It should prove:
|
|||||||
- Public domain support.
|
- Public domain support.
|
||||||
- Alpha-node adoption.
|
- Alpha-node adoption.
|
||||||
|
|
||||||
Once Saleor is clean, the app system is credible.
|
Once a complex stack is clean, the app system is credible.
|
||||||
|
|
||||||
## Implementation Phases
|
## Implementation Phases
|
||||||
|
|
||||||
@ -364,7 +365,7 @@ Once Saleor is clean, the app system is credible.
|
|||||||
- Add adoption logic for existing containers.
|
- Add adoption logic for existing containers.
|
||||||
- Add migration metadata.
|
- Add migration metadata.
|
||||||
- Migrate simple apps.
|
- Migrate simple apps.
|
||||||
- Migrate Saleor.
|
- Migrate a serious multi-container app once the stack model is stable.
|
||||||
- Keep rollback.
|
- Keep rollback.
|
||||||
- Prove reboot recovery with repeated clean post-reboot lifecycle passes.
|
- Prove reboot recovery with repeated clean post-reboot lifecycle passes.
|
||||||
- Preserve Nostr signer bridges, Bitcoin dependency wait states, and public launch ports during adoption.
|
- Preserve Nostr signer bridges, Bitcoin dependency wait states, and public launch ports during adoption.
|
||||||
@ -382,10 +383,10 @@ Once Saleor is clean, the app system is credible.
|
|||||||
Add commands like:
|
Add commands like:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
archy app validate apps/saleor
|
archy app validate apps/example-commerce
|
||||||
archy app render apps/saleor
|
archy app render apps/example-commerce
|
||||||
archy app install apps/saleor
|
archy app install apps/example-commerce
|
||||||
archy app test apps/saleor
|
archy app test apps/example-commerce
|
||||||
```
|
```
|
||||||
|
|
||||||
Developers should be able to package an app without understanding Archipelago internals.
|
Developers should be able to package an app without understanding Archipelago internals.
|
||||||
@ -405,7 +406,7 @@ Public explanation:
|
|||||||
- Routing/public proxy integration: 1-2 weeks.
|
- Routing/public proxy integration: 1-2 weeks.
|
||||||
- Hooks/secrets/backups: 2-3 weeks.
|
- Hooks/secrets/backups: 2-3 weeks.
|
||||||
- First migrations: 2-4 weeks.
|
- First migrations: 2-4 weeks.
|
||||||
- Saleor reference migration: 1-2 weeks.
|
- Complex stack reference migration: 1-2 weeks.
|
||||||
- Cleanup/docs/tooling: 2-3 weeks.
|
- Cleanup/docs/tooling: 2-3 weeks.
|
||||||
|
|
||||||
Total estimate: 8-14 weeks of serious work for an excellent system.
|
Total estimate: 8-14 weeks of serious work for an excellent system.
|
||||||
@ -438,5 +439,5 @@ Minimum viable version: 3-5 weeks.
|
|||||||
3. Finish post-reboot adoption and stale scanner-state handling for migrated apps.
|
3. Finish post-reboot adoption and stale scanner-state handling for migrated apps.
|
||||||
4. Convert remaining multi-container legacy stacks to a manifest-owned model without deleting data.
|
4. Convert remaining multi-container legacy stacks to a manifest-owned model without deleting data.
|
||||||
5. Add developer tooling around the current `manifest.yml` contract: validate, render, local install, lifecycle test.
|
5. Add developer tooling around the current `manifest.yml` contract: validate, render, local install, lifecycle test.
|
||||||
6. Migrate Saleor or another serious multi-container app as the proof package once the stack model is stable.
|
6. Migrate a serious multi-container app as the proof package once the stack model is stable.
|
||||||
7. Leave Bitcoin/LND/core services as managed infrastructure until the package system is proven for normal apps.
|
7. Leave Bitcoin/LND/core services as managed infrastructure until the package system is proven for normal apps.
|
||||||
|
|||||||
@ -64,32 +64,6 @@
|
|||||||
"bitcoin-knots"
|
"bitcoin-knots"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "saleor",
|
|
||||||
"title": "Saleor",
|
|
||||||
"version": "3.23",
|
|
||||||
"description": "Composable commerce platform with customer storefront, GraphQL API, dashboard, worker, mail testing, and tracing.",
|
|
||||||
"icon": "/assets/img/app-icons/saleor.svg",
|
|
||||||
"author": "Saleor",
|
|
||||||
"category": "commerce",
|
|
||||||
"tier": "recommended",
|
|
||||||
"dockerImage": "ghcr.io/saleor/saleor:3.23",
|
|
||||||
"repoUrl": "https://github.com/saleor/saleor",
|
|
||||||
"containerConfig": {
|
|
||||||
"ports": [
|
|
||||||
"9011:80",
|
|
||||||
"9010:80",
|
|
||||||
"8000:8000",
|
|
||||||
"8025:8025",
|
|
||||||
"16686:16686"
|
|
||||||
],
|
|
||||||
"volumes": [
|
|
||||||
"/var/lib/archipelago/saleor:/app/media",
|
|
||||||
"/var/lib/archipelago/saleor-db:/var/lib/postgresql/data"
|
|
||||||
],
|
|
||||||
"notes": "Installed as a Saleor stack: customer storefront on 9011, admin dashboard on 9010, API on 8000, Mailpit on 8025, and Jaeger on 16686. Supporting containers include PostgreSQL, Valkey, Celery worker, and services required by Saleor."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "mempool",
|
"id": "mempool",
|
||||||
"title": "Mempool Explorer",
|
"title": "Mempool Explorer",
|
||||||
|
|||||||
@ -4,7 +4,8 @@ export function useCollapsingHeaderTabs(
|
|||||||
headerRef: Ref<HTMLElement | null>,
|
headerRef: Ref<HTMLElement | null>,
|
||||||
primaryRef: Ref<HTMLElement | null>,
|
primaryRef: Ref<HTMLElement | null>,
|
||||||
tabsProbeRef: Ref<HTMLElement | null>,
|
tabsProbeRef: Ref<HTMLElement | null>,
|
||||||
minSearchWidth = 176
|
minSearchWidth = 176,
|
||||||
|
minTabsWidth = 260
|
||||||
) {
|
) {
|
||||||
const collapsed = ref(false)
|
const collapsed = ref(false)
|
||||||
let resizeObserver: ResizeObserver | null = null
|
let resizeObserver: ResizeObserver | null = null
|
||||||
@ -17,7 +18,9 @@ export function useCollapsingHeaderTabs(
|
|||||||
const primaryWidth = primaryRef.value?.getBoundingClientRect().width ?? 0
|
const primaryWidth = primaryRef.value?.getBoundingClientRect().width ?? 0
|
||||||
const tabsWidth = probe.getBoundingClientRect().width
|
const tabsWidth = probe.getBoundingClientRect().width
|
||||||
const gapWidth = 48
|
const gapWidth = 48
|
||||||
collapsed.value = primaryWidth + tabsWidth + minSearchWidth + gapWidth > header.clientWidth
|
const fullTabsFit = primaryWidth + tabsWidth + minSearchWidth + gapWidth <= header.clientWidth
|
||||||
|
const usableTabsFit = primaryWidth + minTabsWidth + minSearchWidth + gapWidth <= header.clientWidth
|
||||||
|
collapsed.value = !fullTabsFit && !usableTabsFit
|
||||||
}
|
}
|
||||||
|
|
||||||
function scheduleMeasure() {
|
function scheduleMeasure() {
|
||||||
|
|||||||
@ -269,12 +269,46 @@ input[type="radio"]:active + * {
|
|||||||
max-width: min(360px, 34vw);
|
max-width: min(360px, 34vw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-header-desktop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header-mobile {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header-inline-tabs {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) and (max-width: 920px) {
|
||||||
|
.app-header-inline-tabs {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 921px) {
|
||||||
|
.app-header-desktop {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header-mobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.category-tabs-wide {
|
.category-tabs-wide {
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
width: max-content;
|
width: max-content;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: visible;
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-tabs-wide::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-tabs-wide .mode-switcher-btn {
|
.category-tabs-wide .mode-switcher-btn {
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<!-- Nav header -- tabs + categories + search -->
|
<!-- Nav header -- tabs + categories + search -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<!-- Desktop: page tabs + category tabs + search -->
|
<!-- Desktop: page tabs + category tabs + search -->
|
||||||
<div ref="appsHeaderRef" class="hidden md:flex items-center gap-4 relative">
|
<div ref="appsHeaderRef" class="app-header-desktop items-center gap-4 relative">
|
||||||
<div ref="appsPrimaryRef" class="flex-shrink-0">
|
<div ref="appsPrimaryRef" class="flex-shrink-0">
|
||||||
<div class="mode-switcher hidden md:inline-flex">
|
<div class="mode-switcher hidden md:inline-flex">
|
||||||
<button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'apps' }" @click="activeTab = 'apps'; router.replace({ query: {} })">My Apps</button>
|
<button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'apps' }" @click="activeTab = 'apps'; router.replace({ query: {} })">My Apps</button>
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'websites' }" @click="activeTab = 'websites'; router.replace({ query: { tab: 'websites' } })">Websites</button>
|
<button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'websites' }" @click="activeTab = 'websites'; router.replace({ query: { tab: 'websites' } })">Websites</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="activeTab === 'apps' && categoriesWithApps.length > 1 && !collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex flex-shrink-0">
|
<div v-show="activeTab === 'apps' && categoriesWithApps.length > 1 && !collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex">
|
||||||
<button
|
<button
|
||||||
v-for="category in categoriesWithApps"
|
v-for="category in categoriesWithApps"
|
||||||
:key="category.id"
|
:key="category.id"
|
||||||
@ -68,26 +68,43 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Mobile: search + sideload button (tabs handled by Dashboard.vue header) -->
|
<!-- Compact: tabs for tablet, categories, search + sideload -->
|
||||||
<div class="md:hidden flex items-center gap-2">
|
<div class="app-header-mobile mb-4">
|
||||||
<input
|
<div class="app-header-inline-tabs mode-switcher mode-switcher-full mb-3">
|
||||||
v-model="searchQuery"
|
<button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'apps' }" @click="activeTab = 'apps'; router.replace({ query: {} })">My Apps</button>
|
||||||
type="text"
|
<RouterLink to="/dashboard/discover" class="mode-switcher-btn">App Store</RouterLink>
|
||||||
:placeholder="t('apps.searchPlaceholder')"
|
<button class="mode-switcher-btn" :class="{ 'mode-switcher-btn-active': activeTab === 'websites' }" @click="activeTab = 'websites'; router.replace({ query: { tab: 'websites' } })">Websites</button>
|
||||||
:aria-label="t('apps.searchLabel')"
|
</div>
|
||||||
class="min-w-0 flex-1 px-4 py-3 bg-white/10 border border-white/20 rounded-lg text-white placeholder-white/50 focus:outline-none focus:border-white/40 transition-colors"
|
<div v-if="activeTab === 'apps' && categoriesWithApps.length > 1" class="mobile-category-strip mb-3" aria-label="My Apps categories">
|
||||||
/>
|
<button
|
||||||
<button
|
v-for="category in categoriesWithApps"
|
||||||
type="button"
|
:key="category.id"
|
||||||
class="sideload-icon-btn sideload-icon-btn-mobile"
|
@click="selectedCategory = category.id"
|
||||||
aria-label="Sideload app"
|
class="mobile-category-pill"
|
||||||
title="Sideload app"
|
:class="{ 'mobile-category-pill-active': selectedCategory === category.id }"
|
||||||
@click="showSideload = true"
|
type="button"
|
||||||
>
|
>{{ category.name }}</button>
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
</div>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 16V4m0 0l-4 4m4-4l4 4M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2" />
|
<div class="flex items-center gap-2">
|
||||||
</svg>
|
<input
|
||||||
</button>
|
v-model="searchQuery"
|
||||||
|
type="text"
|
||||||
|
:placeholder="t('apps.searchPlaceholder')"
|
||||||
|
:aria-label="t('apps.searchLabel')"
|
||||||
|
class="min-w-0 flex-1 px-4 py-3 bg-white/10 border border-white/20 rounded-lg text-white placeholder-white/50 focus:outline-none focus:border-white/40 transition-colors"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="sideload-icon-btn sideload-icon-btn-mobile"
|
||||||
|
aria-label="Sideload app"
|
||||||
|
title="Sideload app"
|
||||||
|
@click="showSideload = true"
|
||||||
|
>
|
||||||
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 16V4m0 0l-4 4m4-4l4 4M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<!-- Navigation Bar (always at top) -->
|
<!-- Navigation Bar (always at top) -->
|
||||||
<div>
|
<div>
|
||||||
<!-- Desktop: tabs + categories + search -->
|
<!-- Desktop: tabs + categories + search -->
|
||||||
<div ref="discoverHeaderRef" class="hidden md:flex mb-6 items-center gap-4 relative">
|
<div ref="discoverHeaderRef" class="app-header-desktop mb-6 items-center gap-4 relative">
|
||||||
<div ref="discoverPrimaryRef" class="flex-shrink-0">
|
<div ref="discoverPrimaryRef" class="flex-shrink-0">
|
||||||
<div class="mode-switcher hidden md:inline-flex">
|
<div class="mode-switcher hidden md:inline-flex">
|
||||||
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
|
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
|
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex flex-shrink-0">
|
<div v-show="!collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex">
|
||||||
<button
|
<button
|
||||||
v-for="section in appStoreSections"
|
v-for="section in appStoreSections"
|
||||||
:key="section.id"
|
:key="section.id"
|
||||||
@ -59,7 +59,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Mobile: categories + search -->
|
<!-- Mobile: categories + search -->
|
||||||
<div class="md:hidden mb-4">
|
<div class="app-header-mobile mb-4">
|
||||||
|
<div class="app-header-inline-tabs mode-switcher mode-switcher-full mb-3">
|
||||||
|
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
|
||||||
|
<RouterLink to="/dashboard/discover" class="mode-switcher-btn mode-switcher-btn-active">App Store</RouterLink>
|
||||||
|
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
|
||||||
|
</div>
|
||||||
<div class="flex items-center gap-2 mb-3">
|
<div class="flex items-center gap-2 mb-3">
|
||||||
<span class="discover-terminal-tag">discover</span>
|
<span class="discover-terminal-tag">discover</span>
|
||||||
<h1 class="text-lg font-bold text-white">App Store</h1>
|
<h1 class="text-lg font-bold text-white">App Store</h1>
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<!-- Header Section -->
|
<!-- Header Section -->
|
||||||
<div>
|
<div>
|
||||||
<!-- Desktop: tabs + categories + search -->
|
<!-- Desktop: tabs + categories + search -->
|
||||||
<div ref="marketplaceHeaderRef" class="hidden md:flex mb-4 items-center gap-4 relative">
|
<div ref="marketplaceHeaderRef" class="app-header-desktop mb-4 items-center gap-4 relative">
|
||||||
<div ref="marketplacePrimaryRef" class="flex-shrink-0">
|
<div ref="marketplacePrimaryRef" class="flex-shrink-0">
|
||||||
<div class="mode-switcher hidden md:inline-flex">
|
<div class="mode-switcher hidden md:inline-flex">
|
||||||
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
|
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
|
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="!collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex flex-shrink-0">
|
<div v-show="!collapseCategories" class="mode-switcher category-tabs-wide hidden md:inline-flex">
|
||||||
<button
|
<button
|
||||||
v-for="section in appStoreSections"
|
v-for="section in appStoreSections"
|
||||||
:key="section.id"
|
:key="section.id"
|
||||||
@ -60,7 +60,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Mobile: categories + search (tabs handled by Dashboard.vue header) -->
|
<!-- Mobile: categories + search (tabs handled by Dashboard.vue header) -->
|
||||||
<div class="md:hidden mb-4">
|
<div class="app-header-mobile mb-4">
|
||||||
|
<div class="app-header-inline-tabs mode-switcher mode-switcher-full mb-3">
|
||||||
|
<RouterLink to="/dashboard/apps" class="mode-switcher-btn">My Apps</RouterLink>
|
||||||
|
<RouterLink to="/dashboard/discover" class="mode-switcher-btn mode-switcher-btn-active">App Store</RouterLink>
|
||||||
|
<RouterLink to="/dashboard/apps?tab=websites" class="mode-switcher-btn">Websites</RouterLink>
|
||||||
|
</div>
|
||||||
<div class="flex items-center gap-2 mb-3">
|
<div class="flex items-center gap-2 mb-3">
|
||||||
<span class="discover-terminal-tag">discover</span>
|
<span class="discover-terminal-tag">discover</span>
|
||||||
<h1 class="text-lg font-bold text-white">App Store</h1>
|
<h1 class="text-lg font-bold text-white">App Store</h1>
|
||||||
|
|||||||
@ -188,19 +188,6 @@ init()
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
|
<div class="overflow-y-auto flex-1 min-h-0 space-y-6 pr-1">
|
||||||
<!-- v1.7.79-alpha -->
|
|
||||||
<div>
|
|
||||||
<div class="flex items-center gap-2 mb-3">
|
|
||||||
<span class="text-xs font-mono px-2 py-0.5 rounded bg-orange-500/20 text-orange-300">v1.7.79-alpha</span>
|
|
||||||
<span class="text-xs text-white/40">May 20, 2026</span>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
|
||||||
<p>Saleor now includes the official Saleor Storefront as the customer-facing shop on port 9011.</p>
|
|
||||||
<p>Launching Saleor opens the storefront, while the admin dashboard remains on port 9010 with generated admin@example.com credentials shown in Archipelago.</p>
|
|
||||||
<p>Public storefront domains also get same-origin /graphql/ proxying so phones and laptops can reach the local Saleor API through the domain instead of a private node address.</p>
|
|
||||||
<p>Saleor catalog, marketplace, scanner, and app-session metadata now describe the storefront/dashboard/API split explicitly.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- v1.7.78-alpha -->
|
<!-- v1.7.78-alpha -->
|
||||||
<div>
|
<div>
|
||||||
<div class="flex items-center gap-2 mb-3">
|
<div class="flex items-center gap-2 mb-3">
|
||||||
@ -208,7 +195,6 @@ init()
|
|||||||
<span class="text-xs text-white/40">May 20, 2026</span>
|
<span class="text-xs text-white/40">May 20, 2026</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||||
<p>Saleor's validated port 9010 dashboard/API origin settings are now ready for production release, preserving the working test-node install path.</p>
|
|
||||||
<p>NetBird launches now stay on the unified dashboard/proxy origin at port 8087 instead of following stale server URLs on 8086.</p>
|
<p>NetBird launches now stay on the unified dashboard/proxy origin at port 8087 instead of following stale server URLs on 8086.</p>
|
||||||
<p>NetBird proxy routing no longer depends on a hard-coded rootless Podman gateway IP and now includes the upstream management proxy gRPC path.</p>
|
<p>NetBird proxy routing no longer depends on a hard-coded rootless Podman gateway IP and now includes the upstream management proxy gRPC path.</p>
|
||||||
<p>Mobile credential prompts keep long credential lists scrollable and the Cancel/Continue buttons reachable in both My Apps and the mobile icon grid.</p>
|
<p>Mobile credential prompts keep long credential lists scrollable and the Cancel/Continue buttons reachable in both My Apps and the mobile icon grid.</p>
|
||||||
@ -222,8 +208,7 @@ init()
|
|||||||
<span class="text-xs text-white/40">May 20, 2026</span>
|
<span class="text-xs text-white/40">May 20, 2026</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||||
<p>Saleor now installs on dashboard port 9010 instead of conflicting with Portainer on 9000, keeps its API on 8000, creates or repairs the admin@example.com staff account after sample data loads, and starts cleanly with the correct dashboard mount path.</p>
|
<p>Apps with generated first-use credentials now show them in Archipelago before launch and in App Details.</p>
|
||||||
<p>Apps with generated first-use credentials now show them in Archipelago before launch and in App Details. Saleor exposes copyable admin email/password fields so the dashboard login screen is no longer a dead end.</p>
|
|
||||||
<p>NetBird API and OAuth routes now proxy through the stable host-published server port, and the embedded IdP keeps upstream-compatible signing-key refresh settings while the dashboard sends ID tokens to the API so signup no longer lands in an Unauthenticated dashboard state.</p>
|
<p>NetBird API and OAuth routes now proxy through the stable host-published server port, and the embedded IdP keeps upstream-compatible signing-key refresh settings while the dashboard sends ID tokens to the API so signup no longer lands in an Unauthenticated dashboard state.</p>
|
||||||
<p>Transient unnamed Podman helper containers created during app installs are hidden from My Apps, so random generated names like eager_keldysh no longer appear as applications.</p>
|
<p>Transient unnamed Podman helper containers created during app installs are hidden from My Apps, so random generated names like eager_keldysh no longer appear as applications.</p>
|
||||||
<p>Mobile App Store categories are now visible as horizontal chips above the tab bar, Discover is reachable on mobile, category choices update the actual view, and apps that require a real tab open directly from the icon tap.</p>
|
<p>Mobile App Store categories are now visible as horizontal chips above the tab bar, Discover is reachable on mobile, category choices update the actual view, and apps that require a real tab open directly from the icon tap.</p>
|
||||||
@ -236,7 +221,6 @@ init()
|
|||||||
<span class="text-xs text-white/40">May 19, 2026</span>
|
<span class="text-xs text-white/40">May 19, 2026</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
<div class="space-y-3 text-sm text-white/80 pl-3 border-l border-white/10">
|
||||||
<p>Saleor joined the App Store as a recommended commerce stack with dashboard, API, worker, PostgreSQL, Valkey, Mailpit, and Jaeger containers.</p>
|
|
||||||
<p>NetBird repair now rewrites the unified-origin config and recreates the browser-facing proxy/dashboard while preserving existing control-plane data.</p>
|
<p>NetBird repair now rewrites the unified-origin config and recreates the browser-facing proxy/dashboard while preserving existing control-plane data.</p>
|
||||||
<p>Desktop dashboard scrolling hands focus back from the sidebar to the main content when the pointer or wheel moves over the main pane.</p>
|
<p>Desktop dashboard scrolling hands focus back from the sidebar to the main content when the pointer or wheel moves over the main pane.</p>
|
||||||
</div>
|
</div>
|
||||||
@ -251,7 +235,6 @@ init()
|
|||||||
<p>App-session right panels now re-focus the iframe after load and when the frame area is activated, so scrolling works immediately after selecting an app or switching tabs on shorter screens.</p>
|
<p>App-session right panels now re-focus the iframe after load and when the frame area is activated, so scrolling works immediately after selecting an app or switching tabs on shorter screens.</p>
|
||||||
<p>NetBird now uses a unified local launch origin on port 8087 that serves the dashboard and proxies auth/API routes to the server, fixing the Unauthenticated and 404 logout/login loop.</p>
|
<p>NetBird now uses a unified local launch origin on port 8087 that serves the dashboard and proxies auth/API routes to the server, fixing the Unauthenticated and 404 logout/login loop.</p>
|
||||||
<p>Existing NetBird installs are repaired during adopt/start by rewriting the config files and creating the missing dashboard/proxy containers while preserving data.</p>
|
<p>Existing NetBird installs are repaired during adopt/start by rewriting the config files and creating the missing dashboard/proxy containers while preserving data.</p>
|
||||||
<p>Saleor is not in this release yet; it remains pending for separate validation.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- v1.7.73-alpha -->
|
<!-- v1.7.73-alpha -->
|
||||||
|
|||||||
@ -2,10 +2,9 @@
|
|||||||
"version": "1.7.82-alpha",
|
"version": "1.7.82-alpha",
|
||||||
"release_date": "2026-05-22",
|
"release_date": "2026-05-22",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
"Saleor storefront proxying now forwards `X-Forwarded-Host`, fixing Next.js Server Actions requests that compared the browser origin with the internal `storefront-app:3000` upstream host.",
|
"Unsupported Saleor catalog and runtime surfaces are removed until a manifest-owned package exists.",
|
||||||
"Saleor storefront media now routes `/thumbnail/` and `/media/` through the same `9011` proxy to the Saleor API, fixing product image optimizer failures caused by `localhost:8000` media URLs.",
|
"Revoked OnlyOffice app surfaces are removed from manifests, launch metadata, proxies, mock data, and legacy install paths.",
|
||||||
"The Saleor storefront container receives an explicit internal media origin so rewritten media URLs resolve inside the Podman network without exposing private API ports to browsers.",
|
"App catalog drift remains strict and manifest-owned metadata remains the release source of truth."
|
||||||
"Validation passed with `cargo fmt --all --check --manifest-path core/Cargo.toml`, `cargo check -p archipelago --manifest-path core/Cargo.toml`, and live checks on `100.114.134.21` for storefront HTML, static assets, GraphQL, media redirects, and optimized product images."
|
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -2,10 +2,9 @@
|
|||||||
"version": "1.7.82-alpha",
|
"version": "1.7.82-alpha",
|
||||||
"release_date": "2026-05-22",
|
"release_date": "2026-05-22",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
"Saleor storefront proxying now forwards `X-Forwarded-Host`, fixing Next.js Server Actions requests that compared the browser origin with the internal `storefront-app:3000` upstream host.",
|
"Unsupported Saleor catalog and runtime surfaces are removed until a manifest-owned package exists.",
|
||||||
"Saleor storefront media now routes `/thumbnail/` and `/media/` through the same `9011` proxy to the Saleor API, fixing product image optimizer failures caused by `localhost:8000` media URLs.",
|
"Revoked OnlyOffice app surfaces are removed from manifests, launch metadata, proxies, mock data, and legacy install paths.",
|
||||||
"The Saleor storefront container receives an explicit internal media origin so rewritten media URLs resolve inside the Podman network without exposing private API ports to browsers.",
|
"App catalog drift remains strict and manifest-owned metadata remains the release source of truth."
|
||||||
"Validation passed with `cargo fmt --all --check --manifest-path core/Cargo.toml`, `cargo check -p archipelago --manifest-path core/Cargo.toml`, and live checks on `100.114.134.21` for storefront HTML, static assets, GraphQL, media redirects, and optimized product images."
|
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -33,7 +33,6 @@ INTERNAL_MANIFEST_IDS = {
|
|||||||
LEGACY_STACK_CATALOG_IDS = {
|
LEGACY_STACK_CATALOG_IDS = {
|
||||||
"immich",
|
"immich",
|
||||||
"netbird",
|
"netbird",
|
||||||
"saleor",
|
|
||||||
"tailscale",
|
"tailscale",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,14 +54,6 @@ NETBIRD_PROXY_IMAGE="docker.io/library/nginx:1.27-alpine"
|
|||||||
ALPINE_TOR_IMAGE="$ARCHY_REGISTRY/alpine-tor:0.4.8.13"
|
ALPINE_TOR_IMAGE="$ARCHY_REGISTRY/alpine-tor:0.4.8.13"
|
||||||
ADGUARDHOME_IMAGE="$ARCHY_REGISTRY/adguardhome:v0.107.55"
|
ADGUARDHOME_IMAGE="$ARCHY_REGISTRY/adguardhome:v0.107.55"
|
||||||
|
|
||||||
# Saleor stack
|
|
||||||
SALEOR_API_IMAGE="ghcr.io/saleor/saleor:3.23"
|
|
||||||
SALEOR_DASHBOARD_IMAGE="ghcr.io/saleor/saleor-dashboard:3.23"
|
|
||||||
SALEOR_POSTGRES_IMAGE="docker.io/library/postgres:15-alpine"
|
|
||||||
SALEOR_VALKEY_IMAGE="docker.io/valkey/valkey:8.1-alpine"
|
|
||||||
SALEOR_JAEGER_IMAGE="docker.io/jaegertracing/jaeger:latest"
|
|
||||||
SALEOR_MAILPIT_IMAGE="docker.io/axllent/mailpit:latest"
|
|
||||||
|
|
||||||
# Fedimint
|
# Fedimint
|
||||||
FEDIMINT_IMAGE="$ARCHY_REGISTRY/fedimintd:v0.10.0"
|
FEDIMINT_IMAGE="$ARCHY_REGISTRY/fedimintd:v0.10.0"
|
||||||
FEDIMINT_GATEWAY_IMAGE="$ARCHY_REGISTRY/gatewayd:v0.10.0"
|
FEDIMINT_GATEWAY_IMAGE="$ARCHY_REGISTRY/gatewayd:v0.10.0"
|
||||||
|
|||||||
@ -62,38 +62,8 @@ for row in rows:
|
|||||||
forward_port = int(port)
|
forward_port = int(port)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
forward_port = None
|
forward_port = None
|
||||||
is_saleor_dashboard = forward_port == 9010
|
|
||||||
is_saleor_storefront = forward_port == 9011
|
|
||||||
is_saleor = is_saleor_dashboard or is_saleor_storefront
|
|
||||||
graphql_location = ""
|
graphql_location = ""
|
||||||
saleor_proxy_headers = ""
|
extra_proxy_headers = ""
|
||||||
if is_saleor:
|
|
||||||
graphql_location = """
|
|
||||||
location ^~ /graphql/ {
|
|
||||||
proxy_pass http://127.0.0.1:8000/graphql/;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Host 127.0.0.1;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto https;
|
|
||||||
proxy_set_header X-Forwarded-Scheme https;
|
|
||||||
proxy_set_header Origin "";
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
if is_saleor_storefront:
|
|
||||||
saleor_proxy_headers = """
|
|
||||||
proxy_set_header Accept-Encoding "";
|
|
||||||
sub_filter_once off;
|
|
||||||
sub_filter_types text/html application/javascript text/javascript;
|
|
||||||
sub_filter 'http://api:8000/graphql/' 'https://$host/graphql/';
|
|
||||||
"""
|
|
||||||
if is_saleor_dashboard:
|
|
||||||
saleor_proxy_headers = """
|
|
||||||
proxy_set_header Accept-Encoding "";
|
|
||||||
sub_filter_once off;
|
|
||||||
sub_filter_types text/html;
|
|
||||||
sub_filter '</head>' '<script>if(window.__SALEOR_CONFIG__){window.__SALEOR_CONFIG__.API_URL=location.origin+"/graphql/";window.__SALEOR_CONFIG__.EXTENSIONS_API_URL=location.origin+"/graphql/";}</script></head>';
|
|
||||||
"""
|
|
||||||
|
|
||||||
print(f"""
|
print(f"""
|
||||||
server {{
|
server {{
|
||||||
@ -129,7 +99,7 @@ server {{
|
|||||||
proxy_set_header X-Forwarded-Scheme https;
|
proxy_set_header X-Forwarded-Scheme https;
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection "upgrade";
|
proxy_set_header Connection "upgrade";
|
||||||
{saleor_proxy_headers}
|
{extra_proxy_headers}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
""")
|
""")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user