diff --git a/apps/main-app/public/editor/editor.tsx b/apps/main-app/public/editor/editor.tsx
index 05a8c33..7691376 100644
--- a/apps/main-app/public/editor/editor.tsx
+++ b/apps/main-app/public/editor/editor.tsx
@@ -520,12 +520,12 @@ function Dashboard() {
Built by{' '}
- @nekomimi.pet
+ @null.namespaces.me
diff --git a/apps/main-app/src/lib/db.ts b/apps/main-app/src/lib/db.ts
index 9efc860..1b54539 100644
--- a/apps/main-app/src/lib/db.ts
+++ b/apps/main-app/src/lib/db.ts
@@ -512,6 +512,24 @@ export const deleteSite = async (did: string, rkey: string) => {
}
};
+export const upsertSiteCache = async (did: string, rkey: string, recordCid: string, fileCids: Record = {}) => {
+ try {
+ await db`
+ INSERT INTO site_cache (did, rkey, record_cid, file_cids, cached_at, updated_at)
+ VALUES (${did}, ${rkey}, ${recordCid}, ${JSON.stringify(fileCids)}, EXTRACT(EPOCH FROM NOW()), EXTRACT(EPOCH FROM NOW()))
+ ON CONFLICT (did, rkey)
+ DO UPDATE SET
+ record_cid = EXCLUDED.record_cid,
+ file_cids = EXCLUDED.file_cids,
+ updated_at = EXTRACT(EPOCH FROM NOW())
+ `;
+ return { success: true };
+ } catch (err) {
+ console.error('Failed to upsert site cache', err);
+ return { success: false, error: err };
+ }
+};
+
// Get all domains (wisp + custom) mapped to a specific site
export const getDomainsBySite = async (did: string, rkey: string) => {
const domains: Array<{
diff --git a/apps/main-app/src/routes/wisp.ts b/apps/main-app/src/routes/wisp.ts
index 4e16b45..4a514a0 100644
--- a/apps/main-app/src/routes/wisp.ts
+++ b/apps/main-app/src/routes/wisp.ts
@@ -22,7 +22,7 @@ import {
extractSubfsUris
} from '@wispplace/atproto-utils'
import { createManifest } from '@wispplace/fs-utils'
-import { upsertSite } from '../lib/db'
+import { upsertSite, getDomainByDid, updateWispDomainSite, getWispDomainSite, upsertSiteCache } from '../lib/db'
import { createLogger } from '@wispplace/observability'
// import { validateRecord, type Directory } from '@wispplace/lexicons/types/place/wisp/fs'
import { type Directory } from '@wispplace/lexicons/types/place/wisp/fs'
@@ -312,6 +312,30 @@ async function processUploadInBackground(
await upsertSite(did, rkey, siteName);
+ // Cache the empty site for the hosting service
+ try {
+ await upsertSiteCache(did, rkey, record.data.cid, {});
+ } catch (err) {
+ // Don't fail the upload if caching fails
+ logger.warn('Failed to cache site', err);
+ }
+
+ // Auto-map claimed domain to this site if user has a claimed domain with no rkey
+ try {
+ const existingDomain = await getDomainByDid(did);
+ if (existingDomain) {
+ const currentSiteMapping = await getWispDomainSite(did);
+ if (!currentSiteMapping) {
+ // Domain is claimed but not mapped to any site, map it to this new site
+ await updateWispDomainSite(existingDomain, rkey);
+ logger.info(`Auto-mapped domain ${existingDomain} to new site ${siteName}`);
+ }
+ }
+ } catch (err) {
+ // Don't fail the upload if domain mapping fails
+ logger.warn('Failed to auto-map domain to new site', err);
+ }
+
completeUploadJob(jobId, {
success: true,
uri: record.data.uri,
@@ -854,6 +878,35 @@ async function processUploadInBackground(
// Store site in database cache
await upsertSite(did, rkey, siteName);
+ // Cache the site files for the hosting service
+ try {
+ const fileCids: Record = {};
+ for (const blob of uploadedBlobs) {
+ const normalizedPath = blob.filePath.replace(/^[^\/]*\//, '');
+ fileCids[normalizedPath] = blob.result.hash;
+ }
+ await upsertSiteCache(did, rkey, record.data.cid, fileCids);
+ } catch (err) {
+ // Don't fail the upload if caching fails
+ logger.warn('Failed to cache site files', err);
+ }
+
+ // Auto-map claimed domain to this site if user has a claimed domain with no rkey
+ try {
+ const existingDomain = await getDomainByDid(did);
+ if (existingDomain) {
+ const currentSiteMapping = await getWispDomainSite(did);
+ if (!currentSiteMapping) {
+ // Domain is claimed but not mapped to any site, map it to this new site
+ await updateWispDomainSite(existingDomain, rkey);
+ logger.info(`Auto-mapped domain ${existingDomain} to new site ${siteName}`);
+ }
+ }
+ } catch (err) {
+ // Don't fail the upload if domain mapping fails
+ logger.warn('Failed to auto-map domain to new site', err);
+ }
+
// Clean up old subfs records if we had any
if (oldSubfsUris.length > 0) {
console.log(`Cleaning up ${oldSubfsUris.length} old subfs records...`);
@@ -1077,6 +1130,30 @@ export const wispRoutes = (client: NodeOAuthClient, cookieSecret: string) =>
await upsertSite(auth.did, rkey, siteName);
+ // Cache the empty site for the hosting service
+ try {
+ await upsertSiteCache(auth.did, rkey, record.data.cid, {});
+ } catch (err) {
+ // Don't fail the upload if caching fails
+ logger.warn('Failed to cache site', err);
+ }
+
+ // Auto-map claimed domain to this site if user has a claimed domain with no rkey
+ try {
+ const existingDomain = await getDomainByDid(auth.did);
+ if (existingDomain) {
+ const currentSiteMapping = await getWispDomainSite(auth.did);
+ if (!currentSiteMapping) {
+ // Domain is claimed but not mapped to any site, map it to this new site
+ await updateWispDomainSite(existingDomain, rkey);
+ logger.info(`Auto-mapped domain ${existingDomain} to new site ${siteName}`);
+ }
+ }
+ } catch (err) {
+ // Don't fail the upload if domain mapping fails
+ logger.warn('Failed to auto-map domain to new site', err);
+ }
+
return {
success: true,
uri: record.data.uri,