TODO _headers file place.wisp.settings lexicon as a lexiconal way of configuring this
+31
-1
README.md
+31
-1
README.md
···+The hosting service supports Netlify-style `_redirects` files for managing URLs. Place a `_redirects` file in your site root to enable:
-123
hosting-service/EXAMPLE.md
-123
hosting-service/EXAMPLE.md
···-This document demonstrates how HTML path rewriting works when serving sites via the `/s/:identifier/:site/*` route.-When you create a static site with absolute paths like `/style.css` or `/images/logo.png`, these paths work fine when served from the root domain. However, when served from a subdirectory like `/s/alice.bsky.social/mysite/`, these absolute paths break because they resolve to the server root instead of the site root.-The hosting service automatically rewrites absolute paths in HTML files to work correctly in the subdirectory context.-srcset="/s/alice.bsky.social/mysite/images/hero.jpg 1x, /s/alice.bsky.social/mysite/images/hero@2x.jpg 2x"-If you're using relative paths already (like `./style.css` or `../images/logo.png`), they'll work without any rewriting.
···
+134
hosting-service/example-_redirects
+134
hosting-service/example-_redirects
···
···
+215
hosting-service/src/lib/redirects.test.ts
+215
hosting-service/src/lib/redirects.test.ts
···
···
+413
hosting-service/src/lib/redirects.ts
+413
hosting-service/src/lib/redirects.ts
···
···+if ([200, 301, 302].includes(rule.status) && context?.queryParams && !targetPath.includes('?')) {
+168
-6
hosting-service/src/server.ts
+168
-6
hosting-service/src/server.ts
···import { logger, observabilityMiddleware, observabilityErrorHandler, logCollector, errorTracker, metricsCollector } from './lib/observability';import { fileCache, metadataCache, rewrittenHtmlCache, getCacheKey, type FileMetadata } from './lib/cache';·····················
···import { logger, observabilityMiddleware, observabilityErrorHandler, logCollector, errorTracker, metricsCollector } from './lib/observability';import { fileCache, metadataCache, rewrittenHtmlCache, getCacheKey, type FileMetadata } from './lib/cache';+import { loadRedirectRules, matchRedirectRule, parseCookies, parseQueryString, type RedirectRule } from './lib/redirects';······+async function serveFileInternalWithRewrite(did: string, rkey: string, filePath: string, basePath: string) {···············
+1
cli/.gitignore
+1
cli/.gitignore
+3
cli/Cargo.lock
+3
cli/Cargo.lock
+3
cli/Cargo.toml
+3
cli/Cargo.toml
+92
cli/src/blob_map.rs
+92
cli/src/blob_map.rs
···
···
+66
cli/src/cid.rs
+66
cli/src/cid.rs
···
···
+121
-38
cli/src/main.rs
+121
-38
cli/src/main.rs
···············-) -> std::pin::Pin<Box<dyn std::future::Future<Output = miette::Result<Directory<'static>>> + 'a>>······
···+use jacquard::client::{Agent, FileAuthStore, AgentSessionExt, MemoryCredentialSession, AgentSession};······+let existing_blob_map: HashMap<String, (jacquard_common::types::blob::BlobRef<'static>, String)> = {+let (root_dir, total_files, reused_count) = build_directory(agent, &path, &existing_blob_map).await?;···+println!(" Total files: {} ({} reused, {} uploaded)", total_files, reused_count, uploaded_count);···+existing_blobs: &'a HashMap<String, (jacquard_common::types::blob::BlobRef<'static>, String)>,+) -> std::pin::Pin<Box<dyn std::future::Future<Output = miette::Result<(Directory<'static>, usize, usize)>> + 'a>>······