diff --git a/src/assets/favicon.ico b/assets/favicon.ico
similarity index 100%
rename from src/assets/favicon.ico
rename to assets/favicon.ico
diff --git a/src/assets/gif/please-stand-by.gif b/assets/gif/please-stand-by.gif
similarity index 100%
rename from src/assets/gif/please-stand-by.gif
rename to assets/gif/please-stand-by.gif
diff --git a/src/assets/jpg/bitvid.jpg b/assets/jpg/bitvid.jpg
similarity index 100%
rename from src/assets/jpg/bitvid.jpg
rename to assets/jpg/bitvid.jpg
diff --git a/src/assets/jpg/default-profile.jpg b/assets/jpg/default-profile.jpg
similarity index 100%
rename from src/assets/jpg/default-profile.jpg
rename to assets/jpg/default-profile.jpg
diff --git a/src/assets/jpg/video-thumbnail-fallback.jpg b/assets/jpg/video-thumbnail-fallback.jpg
similarity index 100%
rename from src/assets/jpg/video-thumbnail-fallback.jpg
rename to assets/jpg/video-thumbnail-fallback.jpg
diff --git a/src/assets/png/android-chrome-192x192.png b/assets/png/android-chrome-192x192.png
similarity index 100%
rename from src/assets/png/android-chrome-192x192.png
rename to assets/png/android-chrome-192x192.png
diff --git a/src/assets/png/android-chrome-512x512.png b/assets/png/android-chrome-512x512.png
similarity index 100%
rename from src/assets/png/android-chrome-512x512.png
rename to assets/png/android-chrome-512x512.png
diff --git a/src/assets/png/apple-touch-icon.png b/assets/png/apple-touch-icon.png
similarity index 100%
rename from src/assets/png/apple-touch-icon.png
rename to assets/png/apple-touch-icon.png
diff --git a/src/assets/png/bitvid-banner.png b/assets/png/bitvid-banner.png
similarity index 100%
rename from src/assets/png/bitvid-banner.png
rename to assets/png/bitvid-banner.png
diff --git a/src/assets/png/favicon-16x16.png b/assets/png/favicon-16x16.png
similarity index 100%
rename from src/assets/png/favicon-16x16.png
rename to assets/png/favicon-16x16.png
diff --git a/src/assets/png/favicon-32x32.png b/assets/png/favicon-32x32.png
similarity index 100%
rename from src/assets/png/favicon-32x32.png
rename to assets/png/favicon-32x32.png
diff --git a/assets/svg/about-icon.svg b/assets/svg/about-icon.svg
new file mode 100644
index 0000000..855d3a2
--- /dev/null
+++ b/assets/svg/about-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/beacon-icon.svg b/assets/svg/beacon-icon.svg
new file mode 100644
index 0000000..5f8f37e
--- /dev/null
+++ b/assets/svg/beacon-icon.svg
@@ -0,0 +1,7 @@
+
+
+
diff --git a/assets/svg/beta-icon.svg b/assets/svg/beta-icon.svg
new file mode 100644
index 0000000..1fe3453
--- /dev/null
+++ b/assets/svg/beta-icon.svg
@@ -0,0 +1,7 @@
+
+
+
diff --git a/src/assets/svg/bitvid-logo-dark-mode.svg b/assets/svg/bitvid-logo-dark-mode.svg
similarity index 100%
rename from src/assets/svg/bitvid-logo-dark-mode.svg
rename to assets/svg/bitvid-logo-dark-mode.svg
diff --git a/src/assets/svg/bitvid-logo-light-mode.svg b/assets/svg/bitvid-logo-light-mode.svg
similarity index 100%
rename from src/assets/svg/bitvid-logo-light-mode.svg
rename to assets/svg/bitvid-logo-light-mode.svg
diff --git a/assets/svg/blog-icon.svg b/assets/svg/blog-icon.svg
new file mode 100644
index 0000000..f415d7b
--- /dev/null
+++ b/assets/svg/blog-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/src/assets/svg/copy-magnet.svg b/assets/svg/copy-magnet.svg
similarity index 100%
rename from src/assets/svg/copy-magnet.svg
rename to assets/svg/copy-magnet.svg
diff --git a/assets/svg/default-profile.svg b/assets/svg/default-profile.svg
new file mode 100644
index 0000000..b31b553
--- /dev/null
+++ b/assets/svg/default-profile.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/dns-icon.svg b/assets/svg/dns-icon.svg
new file mode 100644
index 0000000..6bedf6f
--- /dev/null
+++ b/assets/svg/dns-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/explore-icon.svg b/assets/svg/explore-icon.svg
new file mode 100644
index 0000000..2d80429
--- /dev/null
+++ b/assets/svg/explore-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/getting-started-icon.svg b/assets/svg/getting-started-icon.svg
new file mode 100644
index 0000000..dcece7e
--- /dev/null
+++ b/assets/svg/getting-started-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/github-icon.svg b/assets/svg/github-icon.svg
new file mode 100644
index 0000000..ffb9088
--- /dev/null
+++ b/assets/svg/github-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/guidelines-icon.svg b/assets/svg/guidelines-icon.svg
new file mode 100644
index 0000000..9933f81
--- /dev/null
+++ b/assets/svg/guidelines-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/home-icon.svg b/assets/svg/home-icon.svg
new file mode 100644
index 0000000..2c7c1df
--- /dev/null
+++ b/assets/svg/home-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/ipns-icon.svg b/assets/svg/ipns-icon.svg
new file mode 100644
index 0000000..c6fe78a
--- /dev/null
+++ b/assets/svg/ipns-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/links-icon.svg b/assets/svg/links-icon.svg
new file mode 100644
index 0000000..477a431
--- /dev/null
+++ b/assets/svg/links-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/mobile-sidebar-menu-icon.svg b/assets/svg/mobile-sidebar-menu-icon.svg
new file mode 100644
index 0000000..fa9a60c
--- /dev/null
+++ b/assets/svg/mobile-sidebar-menu-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/assets/svg/nostr-icon.svg b/assets/svg/nostr-icon.svg
new file mode 100644
index 0000000..e32ea7b
--- /dev/null
+++ b/assets/svg/nostr-icon.svg
@@ -0,0 +1,12 @@
+
+
+
diff --git a/assets/svg/roadmap-icon.svg b/assets/svg/roadmap-icon.svg
new file mode 100644
index 0000000..6bd0948
--- /dev/null
+++ b/assets/svg/roadmap-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/src/assets/svg/share-video.svg b/assets/svg/share-video.svg
similarity index 100%
rename from src/assets/svg/share-video.svg
rename to assets/svg/share-video.svg
diff --git a/assets/svg/subscriptions-icon.svg b/assets/svg/subscriptions-icon.svg
new file mode 100644
index 0000000..46ff49d
--- /dev/null
+++ b/assets/svg/subscriptions-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/src/assets/svg/video-settings-gear.svg b/assets/svg/video-settings-gear.svg
similarity index 100%
rename from src/assets/svg/video-settings-gear.svg
rename to assets/svg/video-settings-gear.svg
diff --git a/bitvid_logo/beacon-icon.svg b/bitvid_logo/beacon-icon.svg
new file mode 100644
index 0000000..5f8f37e
--- /dev/null
+++ b/bitvid_logo/beacon-icon.svg
@@ -0,0 +1,7 @@
+
+
+
diff --git a/bitvid_logo/dns-icon.svg b/bitvid_logo/dns-icon.svg
new file mode 100644
index 0000000..6bedf6f
--- /dev/null
+++ b/bitvid_logo/dns-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/bitvid_logo/guidelines-icon.svg b/bitvid_logo/guidelines-icon.svg
new file mode 100644
index 0000000..9933f81
--- /dev/null
+++ b/bitvid_logo/guidelines-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/bitvid_logo/home-icon.svg b/bitvid_logo/home-icon.svg
new file mode 100644
index 0000000..2c7c1df
--- /dev/null
+++ b/bitvid_logo/home-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/bitvid_logo/ipns-icon.svg b/bitvid_logo/ipns-icon.svg
new file mode 100644
index 0000000..c6fe78a
--- /dev/null
+++ b/bitvid_logo/ipns-icon.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/blog.html b/blog.html
new file mode 100644
index 0000000..bd41b46
--- /dev/null
+++ b/blog.html
@@ -0,0 +1,30444 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/application-form.html b/components/application-form.html
similarity index 100%
rename from src/components/application-form.html
rename to components/application-form.html
diff --git a/src/components/bug-fix-form.html b/components/bug-fix-form.html
similarity index 100%
rename from src/components/bug-fix-form.html
rename to components/bug-fix-form.html
diff --git a/src/components/content-appeals-form.html b/components/content-appeals-form.html
similarity index 100%
rename from src/components/content-appeals-form.html
rename to components/content-appeals-form.html
diff --git a/components/disclaimer.html b/components/disclaimer.html
new file mode 100644
index 0000000..a190d9c
--- /dev/null
+++ b/components/disclaimer.html
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Welcome to bitvid
+
+
+
+
+ This platform is currently in development and only supports Chrome
+ and Firefox-based browsers. Other browsers are not supported at
+ this time. You may encounter bugs or missing features. Give it a
+ sec. Videos might take 10 to 60 seconds to load initially.
+
+
+
+ bitvid is a decentralized video platform where content is shared
+ directly between users. We want you to understand a few important
+ points before you continue:
+
+
+
+
+
Early Access Status
+
+ Currently, video posting is invite-only as we carefully scale
+ our platform. While anyone can watch videos, content creation is
+ limited to approved creators. This helps us maintain quality
+ content during our early stages.
+
+
+
+
+ Content Responsibility & Moderation
+
+
+ While we don't host videos directly, we maintain community
+ standards through access control. Users who violate our
+ guidelines may be blocked from accessing the platform. All
+ content must follow local laws and platform guidelines.
+
+
+
+
Platform Status
+
+ bitvid is a work in progress. Features may change or break, and
+ security improvements are ongoing. Your feedback and patience
+ help us build a better platform.
+
+
+
+
Get Involved
+
+ Are you a developer? We'd love your help! Visit our GitHub
+ repository to contribute to building the future of decentralized
+ video sharing.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/feature-request-form.html b/components/feature-request-form.html
similarity index 100%
rename from src/components/feature-request-form.html
rename to components/feature-request-form.html
diff --git a/src/components/general-feedback-form.html b/components/general-feedback-form.html
similarity index 100%
rename from src/components/general-feedback-form.html
rename to components/general-feedback-form.html
diff --git a/src/components/iframe_forms/iframe-application-form.html b/components/iframe_forms/iframe-application-form.html
similarity index 100%
rename from src/components/iframe_forms/iframe-application-form.html
rename to components/iframe_forms/iframe-application-form.html
diff --git a/src/components/iframe_forms/iframe-bug-fix-form.html b/components/iframe_forms/iframe-bug-fix-form.html
similarity index 100%
rename from src/components/iframe_forms/iframe-bug-fix-form.html
rename to components/iframe_forms/iframe-bug-fix-form.html
diff --git a/src/components/iframe_forms/iframe-content-appeals-form.html b/components/iframe_forms/iframe-content-appeals-form.html
similarity index 100%
rename from src/components/iframe_forms/iframe-content-appeals-form.html
rename to components/iframe_forms/iframe-content-appeals-form.html
diff --git a/src/components/iframe_forms/iframe-feedback-form.html b/components/iframe_forms/iframe-feedback-form.html
similarity index 100%
rename from src/components/iframe_forms/iframe-feedback-form.html
rename to components/iframe_forms/iframe-feedback-form.html
diff --git a/src/components/iframe_forms/iframe-request-form.html b/components/iframe_forms/iframe-request-form.html
similarity index 100%
rename from src/components/iframe_forms/iframe-request-form.html
rename to components/iframe_forms/iframe-request-form.html
diff --git a/src/components/login-modal.html b/components/login-modal.html
similarity index 100%
rename from src/components/login-modal.html
rename to components/login-modal.html
diff --git a/src/components/profile-modal.html b/components/profile-modal.html
similarity index 98%
rename from src/components/profile-modal.html
rename to components/profile-modal.html
index c453d32..1b9c5f9 100644
--- a/src/components/profile-modal.html
+++ b/components/profile-modal.html
@@ -54,7 +54,7 @@
diff --git a/components/sidebar.html b/components/sidebar.html
new file mode 100644
index 0000000..9756ccf
--- /dev/null
+++ b/components/sidebar.html
@@ -0,0 +1,248 @@
+
diff --git a/src/components/upload-modal.html b/components/upload-modal.html
similarity index 100%
rename from src/components/upload-modal.html
rename to components/upload-modal.html
diff --git a/src/components/video-modal.html b/components/video-modal.html
similarity index 100%
rename from src/components/video-modal.html
rename to components/video-modal.html
diff --git a/src/content/about.md b/content/about.md
similarity index 95%
rename from src/content/about.md
rename to content/about.md
index fcae05c..d61f257 100644
--- a/src/content/about.md
+++ b/content/about.md
@@ -1,7 +1,3 @@
-
-
-# About bitvid
-
Welcome to bitvid, a new kind of video platform that puts you in control. Unlike traditional video sites that keep your content on their servers, bitvid lets videos flow directly between creators and viewers. Think of it like a digital potluck where everyone brings and shares content directly with each other!
## What Makes bitvid Different?
diff --git a/src/content/community-guidelines.md b/content/community-guidelines.md
similarity index 99%
rename from src/content/community-guidelines.md
rename to content/community-guidelines.md
index 7b3a771..adc097f 100644
--- a/src/content/community-guidelines.md
+++ b/content/community-guidelines.md
@@ -1,5 +1,3 @@
-# **bitvid Community Guidelines**
-
Welcome to **bitvid**, a decentralized video-sharing platform built on Nostr. These Community Guidelines outline the types of content allowed and prohibited on the platform. As bitvid is still in early access, enforcement will occur at the client level, meaning violations will result in content being blocked from display rather than removed from relays. These policies will evolve as we implement robust user blocking and reporting features.
## **1. Content Principles**
diff --git a/src/content/getting-started.md b/content/getting-started.md
similarity index 98%
rename from src/content/getting-started.md
rename to content/getting-started.md
index 8104f9c..88e2c88 100644
--- a/src/content/getting-started.md
+++ b/content/getting-started.md
@@ -1,5 +1,3 @@
-# Getting Started with bitvid
-
Ready to jump in? Here's everything you need to know to start watching and sharing videos on bitvid.
## Watching Videos
diff --git a/src/content/ipns.md b/content/ipns.md
similarity index 100%
rename from src/content/ipns.md
rename to content/ipns.md
diff --git a/content/links.md b/content/links.md
new file mode 100644
index 0000000..6d815b7
--- /dev/null
+++ b/content/links.md
@@ -0,0 +1,139 @@
+Here is a collection of links to forms and pages.
+
+---
+
+## Forms
+
+---
+
+### Application Form
+
+Main - [bitvid.network?modal=application](https://bitvid.network?modal=application)
+
+Beta - [beta.bitvid.network?modal=application](https://beta.bitvid.network?modal=application)
+
+---
+
+### Bug Fix Form
+
+Main - [bitvid.network?modal=bug](https://bitvid.network?modal=bug)
+
+Beta - [beta.bitvid.network?modal=bug](https://beta.bitvid.network?modal=bug)
+
+---
+
+### Content Appeals Form
+
+Main - [bitvid.network?modal=appeals](https://bitvid.network?modal=appeals)
+
+Beta - [beta.bitvid.network?modal=appeals](https://beta.bitvid.network?modal=appeals)
+
+---
+
+### Feature Request Form
+
+Main - [bitvid.network?modal=feature](https://bitvid.network?modal=feature)
+
+Beta - [beta.bitvid.network?modal=feature](https://beta.bitvid.network?modal=feature)
+
+---
+
+### General Feedback Form
+
+Main - [bitvid.network?modal=feedback](https://bitvid.network?modal=feedback)
+
+Beta - [beta.bitvid.network?modal=feedback](https://beta.bitvid.network?modal=feedback)
+
+---
+
+## Views
+
+---
+
+### Home
+
+Main - [bitvid.network#view=most-recent-videos](https://bitvid.network#view=most-recent-videos)
+
+Beta - [beta.bitvid.network#view=most-recent-videos](https://beta.bitvid.network#view=most-recent-videos)
+
+---
+
+### Explore
+
+Main - [bitvid.network#view=explore](https://bitvid.network#view=explore)
+
+Beta - [beta.bitvid.network#view=explore](https://beta.bitvid.network#view=explore)
+
+---
+
+### Subscriptions
+
+_Requires Nostr login_
+
+Main - [bitvid.network#view=subscriptions](https://bitvid.network#view=subscriptions)
+
+Beta - [beta.bitvid.network#view=subscriptions](https://beta.bitvid.network#view=subscriptions)
+
+---
+
+### About
+
+Main - [bitvid.network#view=about](https://bitvid.network#view=about)
+
+Beta - [beta.bitvid.network#view=about](https://beta.bitvid.network#view=about)
+
+---
+
+### Guidelines
+
+Main - [bitvid.network#view=community-guidelines](https://bitvid.network#view=community-guidelines)
+
+Beta - [beta.bitvid.network#view=community-guidelines](https://beta.bitvid.network#view=community-guidelines)
+
+---
+
+### Getting Started
+
+Main - [bitvid.network#view=getting-started](https://bitvid.network#view=getting-started)
+
+Beta - [beta.bitvid.network#view=getting-started](https://beta.bitvid.network#view=getting-started)
+
+---
+
+### Roadmap
+
+Main - [bitvid.network#view=roadmap](https://bitvid.network#view=roadmap)
+
+Beta - [beta.bitvid.network#view=roadmap](https://beta.bitvid.network#view=roadmap)
+
+---
+
+### βeacon
+
+Main - [bitvid.network/torrent/beacon.html](https://bitvid.network/torrent/beacon.html)
+
+Beta - [beta.bitvid.network/torrent/beacon.html](https://beta.bitvid.network/torrent/beacon.html)
+
+---
+
+### Beta
+
+Main - [bitvid.network](https://bitvid.network)
+
+Beta - [beta.bitvid.network](https://beta.bitvid.network)
+
+---
+
+### Links
+
+Main - [bitvid.network#view=links](https://bitvid.network#view=links)
+
+Beta - [beta.bitvid.network#view=links](https://beta.bitvid.network#view=links)
+
+---
+
+### IPNS
+
+Main - [bitvid.network#view=ipns](https://bitvid.network#view=ipns)
+
+Beta - [beta.bitvid.network#view=ipns](https://beta.bitvid.network#view=ipns)
diff --git a/src/content/roadmap.md b/content/roadmap.md
similarity index 87%
rename from src/content/roadmap.md
rename to content/roadmap.md
index 824c7a2..13cbe8a 100644
--- a/src/content/roadmap.md
+++ b/content/roadmap.md
@@ -1,5 +1,3 @@
-# Roadmap and Bug List
-
## UI Enhancements
- Add a copy Magnet button labeled "Seed".
@@ -13,10 +11,6 @@
## Bug Fixes
-- Fix public key wrapping issue on smaller screens.
-- Fix video editing failures.
-- Resolve issue where reopening the same video doesn't work after closing the video player.
-- Address "Video playback error: MEDIA_ELEMENT_ERROR: Empty src attribute" error.
- Fix "Dev Mode" publishing "Live Mode" notes—add a flag for dev mode posts.
## Feature Additions
diff --git a/src/content/roadmap/02_bitvid_Enhanced_Migration_of_Note_Spec_Logic.md b/content/roadmap/02_bitvid_Enhanced_Migration_of_Note_Spec_Logic.md
similarity index 100%
rename from src/content/roadmap/02_bitvid_Enhanced_Migration_of_Note_Spec_Logic.md
rename to content/roadmap/02_bitvid_Enhanced_Migration_of_Note_Spec_Logic.md
diff --git a/src/content/roadmap/03_bitvid_Enhanced_Nostr_Video_&_Audio_Note_Specification_Version 3.md b/content/roadmap/03_bitvid_Enhanced_Nostr_Video_&_Audio_Note_Specification_Version 3.md
similarity index 100%
rename from src/content/roadmap/03_bitvid_Enhanced_Nostr_Video_&_Audio_Note_Specification_Version 3.md
rename to content/roadmap/03_bitvid_Enhanced_Nostr_Video_&_Audio_Note_Specification_Version 3.md
diff --git a/src/content/roadmap/04_bitvid_Enhanced_Profile_Channel_Views_Specification.md b/content/roadmap/04_bitvid_Enhanced_Profile_Channel_Views_Specification.md
similarity index 100%
rename from src/content/roadmap/04_bitvid_Enhanced_Profile_Channel_Views_Specification.md
rename to content/roadmap/04_bitvid_Enhanced_Profile_Channel_Views_Specification.md
diff --git a/src/content/roadmap/05_bitvid_Enhanced_Block_Subscription_&_Reporting_Specification.md b/content/roadmap/05_bitvid_Enhanced_Block_Subscription_&_Reporting_Specification.md
similarity index 100%
rename from src/content/roadmap/05_bitvid_Enhanced_Block_Subscription_&_Reporting_Specification.md
rename to content/roadmap/05_bitvid_Enhanced_Block_Subscription_&_Reporting_Specification.md
diff --git a/src/content/roadmap/06_bitvid_Enhanced_Video_Comment_System_Specification.md b/content/roadmap/06_bitvid_Enhanced_Video_Comment_System_Specification.md
similarity index 100%
rename from src/content/roadmap/06_bitvid_Enhanced_Video_Comment_System_Specification.md
rename to content/roadmap/06_bitvid_Enhanced_Video_Comment_System_Specification.md
diff --git a/src/content/roadmap/07_bitvid_Enhanced_View_Rating_&_Retention_Penalty_Scoring.md b/content/roadmap/07_bitvid_Enhanced_View_Rating_&_Retention_Penalty_Scoring.md
similarity index 100%
rename from src/content/roadmap/07_bitvid_Enhanced_View_Rating_&_Retention_Penalty_Scoring.md
rename to content/roadmap/07_bitvid_Enhanced_View_Rating_&_Retention_Penalty_Scoring.md
diff --git a/src/content/roadmap/08_bitvid_Enhanced_Dynamic_Home_Page_&_Video_Tracking_Specification.md b/content/roadmap/08_bitvid_Enhanced_Dynamic_Home_Page_&_Video_Tracking_Specification.md
similarity index 100%
rename from src/content/roadmap/08_bitvid_Enhanced_Dynamic_Home_Page_&_Video_Tracking_Specification.md
rename to content/roadmap/08_bitvid_Enhanced_Dynamic_Home_Page_&_Video_Tracking_Specification.md
diff --git a/src/content/roadmap/09_bitvid_Enhanced_NIP-35_+_WebRTC_Check_Integration.md b/content/roadmap/09_bitvid_Enhanced_NIP-35_+_WebRTC_Check_Integration.md
similarity index 100%
rename from src/content/roadmap/09_bitvid_Enhanced_NIP-35_+_WebRTC_Check_Integration.md
rename to content/roadmap/09_bitvid_Enhanced_NIP-35_+_WebRTC_Check_Integration.md
diff --git a/src/css/markdown.css b/css/markdown.css
similarity index 100%
rename from src/css/markdown.css
rename to css/markdown.css
diff --git a/src/css/style.css b/css/style.css
similarity index 87%
rename from src/css/style.css
rename to css/style.css
index c8445d4..e8bec95 100644
--- a/src/css/style.css
+++ b/css/style.css
@@ -16,6 +16,9 @@ body {
background-color: var(--color-bg);
color: var(--color-text);
line-height: 1.5;
+ margin: 0;
+ padding: 0;
+ overflow-x: hidden; /* Disable horizontal scrolling */
}
header {
@@ -470,3 +473,56 @@ footer a:hover {
height: 100%;
object-fit: cover;
}
+
+/* Sidebar default states */
+#sidebar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 16rem; /* Tailwind's w-64 */
+ height: 100vh;
+ background-color: #0f172a;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ transition: transform 0.3s ease;
+}
+
+/* Mobile (max-width: 767px): Hide sidebar by default */
+@media (max-width: 767px) {
+ #sidebar {
+ transform: translateX(-100%);
+ }
+ /* When the sidebar-open class is added, slide the sidebar in */
+ #sidebar.sidebar-open {
+ transform: translateX(0);
+ }
+
+ /* Optionally shift main content when sidebar is open */
+ #app.sidebar-open {
+ transform: translateX(16rem);
+ transition: transform 0.3s ease;
+ }
+}
+
+/* Desktop (min-width: 768px): Always show the sidebar */
+@media (min-width: 768px) {
+ #sidebar {
+ transform: translateX(0) !important;
+ }
+}
+
+/* Collapsed/expanded classes if needed on desktop */
+.sidebar-collapsed {
+ width: 4rem;
+}
+.sidebar-expanded {
+ width: 16rem;
+}
+.sidebar-collapsed .sidebar-text {
+ display: none;
+}
+
+/* Example: customizing the border & background in the sidebar */
+#sidebar hr {
+ border-color: rgba(255, 255, 255, 0.1);
+}
diff --git a/src/css/tailwind.min.css b/css/tailwind.min.css
similarity index 100%
rename from src/css/tailwind.min.css
rename to css/tailwind.min.css
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..e707cdd
--- /dev/null
+++ b/index.html
@@ -0,0 +1,168 @@
+
+
+
+
+
+ bitvid | Decentralized Video Sharing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ seed. zap. subscribe.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/js/accessControl.js b/js/accessControl.js
similarity index 100%
rename from src/js/accessControl.js
rename to js/accessControl.js
diff --git a/src/js/app.js b/js/app.js
similarity index 83%
rename from src/js/app.js
rename to js/app.js
index 4891f11..e40a32f 100644
--- a/src/js/app.js
+++ b/js/app.js
@@ -4,7 +4,7 @@ import { loadView } from "./viewManager.js";
import { nostrClient } from "./nostr.js";
import { torrentClient } from "./webtorrent.js";
import { isDevMode } from "./config.js";
-import { disclaimerModal } from "./disclaimer.js";
+import disclaimerModal from "./disclaimer.js";
import { initialBlacklist, initialEventBlacklist } from "./lists.js";
/**
@@ -14,6 +14,48 @@ function fakeDecrypt(str) {
return str.split("").reverse().join("");
}
+/**
+ * Simple IntersectionObserver-based lazy loader for images (or videos).
+ *
+ * Usage:
+ * const mediaLoader = new MediaLoader();
+ * mediaLoader.observe(imgElement);
+ *
+ * This will load the real image source from `imgElement.dataset.lazy`
+ * once the image enters the viewport.
+ */
+class MediaLoader {
+ constructor(rootMargin = "50px") {
+ this.observer = new IntersectionObserver(
+ (entries) => {
+ for (const entry of entries) {
+ if (entry.isIntersecting) {
+ const el = entry.target;
+ const lazySrc = el.dataset.lazy;
+ if (lazySrc) {
+ el.src = lazySrc;
+ delete el.dataset.lazy;
+ }
+ // Stop observing once loaded
+ this.observer.unobserve(el);
+ }
+ }
+ },
+ { rootMargin }
+ );
+ }
+
+ observe(el) {
+ if (el.dataset.lazy) {
+ this.observer.observe(el);
+ }
+ }
+
+ disconnect() {
+ this.observer.disconnect();
+ }
+}
+
class bitvidApp {
constructor() {
// Basic auth/display elements
@@ -22,6 +64,9 @@ class bitvidApp {
this.userStatus = document.getElementById("userStatus") || null;
this.userPubKey = document.getElementById("userPubKey") || null;
+ // Lazy-loading helper for images
+ this.mediaLoader = new MediaLoader();
+
// Optional: a "profile" button or avatar (if used)
this.profileButton = document.getElementById("profileButton") || null;
this.profileAvatar = document.getElementById("profileAvatar") || null;
@@ -65,6 +110,9 @@ class bitvidApp {
this.copyMagnetBtn = null;
this.shareBtn = null;
+ // Hide/Show Subscriptions Link
+ this.subscriptionsLink = null;
+
// Notification containers
this.errorContainer = document.getElementById("errorContainer") || null;
this.successContainer = document.getElementById("successContainer") || null;
@@ -140,18 +188,38 @@ class bitvidApp {
// 4. Connect to Nostr
await nostrClient.init();
+
+ // Grab the "Subscriptions" link by its id in the sidebar
+ this.subscriptionsLink = document.getElementById("subscriptionsLink");
+
const savedPubKey = localStorage.getItem("userPubKey");
if (savedPubKey) {
// Auto-login if a pubkey was saved
this.login(savedPubKey, false);
+
+ // If the user was already logged in, show the Subscriptions link
+ if (this.subscriptionsLink) {
+ this.subscriptionsLink.classList.remove("hidden");
+ }
}
// 5. Setup general event listeners, show disclaimers
this.setupEventListeners();
disclaimerModal.show();
- // 6. Load the default view (most-recent-videos.html)
- await loadView("views/most-recent-videos.html");
+ // 6) Load the default view ONLY if there's no #view= already
+ if (!window.location.hash || !window.location.hash.startsWith("#view=")) {
+ console.log(
+ "[app.init()] No #view= in the URL, loading default home view"
+ );
+ await loadView("views/most-recent-videos.html");
+ } else {
+ console.log(
+ "[app.init()] Found hash:",
+ window.location.hash,
+ "so skipping default load"
+ );
+ }
// 7. Once loaded, get a reference to #videoList
this.videoList = document.getElementById("videoList");
@@ -478,22 +546,36 @@ class bitvidApp {
await this.cleanup();
});
- // 8) Handle back/forward nav => hide video modal
+ // 8) Handle back/forward navigation => hide video modal
window.addEventListener("popstate", async () => {
console.log("[popstate] user navigated back/forward; cleaning modal...");
await this.hideModal();
});
- // Event delegation for the “Application Form” button inside the login modal
+ // 9) Event delegation on the video list container for playing videos
+ if (this.videoList) {
+ this.videoList.addEventListener("click", (event) => {
+ const magnetTrigger = event.target.closest("[data-play-magnet]");
+ if (magnetTrigger) {
+ // For a normal left-click (button 0, no Ctrl/Cmd), prevent navigation:
+ if (event.button === 0 && !event.ctrlKey && !event.metaKey) {
+ event.preventDefault(); // Stop browser from following the href
+ const magnet = magnetTrigger.dataset.playMagnet;
+ this.playVideo(magnet);
+ }
+ }
+ });
+ }
+
+ // 10) Event delegation for the “Application Form” button inside the login modal
document.addEventListener("click", (event) => {
if (event.target && event.target.id === "openApplicationModal") {
- // 1) Hide the login modal
+ // Hide the login modal
const loginModal = document.getElementById("loginModal");
if (loginModal) {
loginModal.classList.add("hidden");
}
-
- // 2) Show the application modal
+ // Show the application modal
const appModal = document.getElementById("nostrFormModal");
if (appModal) {
appModal.classList.remove("hidden");
@@ -511,12 +593,12 @@ class bitvidApp {
{ kinds: [0], authors: [pubkey], limit: 1 },
]);
let displayName = "User";
- let picture = "assets/jpg/default-profile.jpg";
+ let picture = "assets/svg/default-profile.svg";
if (events.length && events[0].content) {
const data = JSON.parse(events[0].content);
displayName = data.name || data.display_name || "User";
- picture = data.picture || "assets/jpg/default-profile.jpg";
+ picture = data.picture || "assets/svg/default-profile.svg";
}
// If you have a top-bar avatar (profileAvatar)
@@ -535,6 +617,56 @@ class bitvidApp {
}
}
+ async fetchAndRenderProfile(pubkey, forceRefresh = false) {
+ const now = Date.now();
+
+ // 1) Check if we have a cached entry
+ const cacheEntry = this.profileCache.get(pubkey);
+ if (!forceRefresh && cacheEntry && now - cacheEntry.timestamp < 60000) {
+ // If it's less than 60 seconds old, just update DOM with it
+ this.updateProfileInDOM(pubkey, cacheEntry.profile);
+ return;
+ }
+
+ // 2) Otherwise, fetch from Nostr
+ try {
+ const userEvents = await nostrClient.pool.list(nostrClient.relays, [
+ { kinds: [0], authors: [pubkey], limit: 1 },
+ ]);
+ if (userEvents.length > 0 && userEvents[0].content) {
+ const data = JSON.parse(userEvents[0].content);
+ const profile = {
+ name: data.name || data.display_name || "Unknown",
+ picture: data.picture || "assets/svg/default-profile.svg",
+ };
+
+ // Cache it
+ this.profileCache.set(pubkey, { profile, timestamp: now });
+ // Update DOM
+ this.updateProfileInDOM(pubkey, profile);
+ }
+ } catch (err) {
+ console.error("Profile fetch error:", err);
+ }
+ }
+
+ updateProfileInDOM(pubkey, profile) {
+ // For any .author-pic[data-pubkey=...]
+ const picEls = document.querySelectorAll(
+ `.author-pic[data-pubkey="${pubkey}"]`
+ );
+ picEls.forEach((el) => {
+ el.src = profile.picture;
+ });
+ // For any .author-name[data-pubkey=...]
+ const nameEls = document.querySelectorAll(
+ `.author-name[data-pubkey="${pubkey}"]`
+ );
+ nameEls.forEach((el) => {
+ el.textContent = profile.name;
+ });
+ }
+
/**
* Actually handle the upload form submission.
*/
@@ -617,6 +749,11 @@ class bitvidApp {
this.profileButton.classList.remove("hidden");
}
+ // Show the "Subscriptions" link if it exists
+ if (this.subscriptionsLink) {
+ this.subscriptionsLink.classList.remove("hidden");
+ }
+
// (Optional) load the user's own Nostr profile
this.loadOwnProfile(pubkey);
@@ -663,6 +800,11 @@ class bitvidApp {
this.profileButton.classList.add("hidden");
}
+ // Hide the Subscriptions link
+ if (this.subscriptionsLink) {
+ this.subscriptionsLink.classList.add("hidden");
+ }
+
// Clear localStorage
localStorage.removeItem("userPubKey");
@@ -701,35 +843,47 @@ class bitvidApp {
* Hide the video modal.
*/
async hideModal() {
- // 1) Clear intervals
+ // 1) Clear intervals, cleanup, etc. (unchanged)
if (this.activeIntervals && this.activeIntervals.length) {
this.activeIntervals.forEach((id) => clearInterval(id));
this.activeIntervals = [];
}
- // 2) Cleanup resources (this stops the torrent, etc.)
+ try {
+ await fetch("/webtorrent/cancel/", { mode: "no-cors" });
+ } catch (err) {
+ // ignore
+ }
await this.cleanup();
- // 3) Hide the modal
+ // 2) Hide the modal
if (this.playerModal) {
this.playerModal.style.display = "none";
this.playerModal.classList.add("hidden");
}
this.currentMagnetUri = null;
- // 4) Revert ?v= param in the URL
- window.history.replaceState({}, "", window.location.pathname);
+ // 3) Remove only `?v=` but **keep** the hash
+ const url = new URL(window.location.href);
+ url.searchParams.delete("v"); // remove ?v= param
+ const newUrl = url.pathname + url.search + url.hash;
+ window.history.replaceState({}, "", newUrl);
}
/**
* Subscribe to videos (older + new) and render them as they come in.
*/
- async loadVideos() {
- console.log("Starting loadVideos...");
+ async loadVideos(forceFetch = false) {
+ console.log("Starting loadVideos... (forceFetch =", forceFetch, ")");
- // We do NOT decode initialEventBlacklist here.
- // That happens once in the constructor, creating this.blacklistedEventIds.
+ // If forceFetch is true, unsubscribe from the old subscription to start fresh
+ if (forceFetch && this.videoSubscription) {
+ // Call unsubscribe on the subscription object directly.
+ this.videoSubscription.unsub();
+ this.videoSubscription = null;
+ }
+ // The rest of your existing logic:
if (!this.videoSubscription) {
if (this.videoList) {
this.videoList.innerHTML = `
@@ -738,7 +892,7 @@ class bitvidApp {
`;
}
- // Create a single subscription
+ // Create a new subscription
this.videoSubscription = nostrClient.subscribeVideos(() => {
const updatedAll = nostrClient.getActiveVideos();
@@ -749,7 +903,7 @@ class bitvidApp {
return false;
}
- // 2) Check author (if you’re also blacklisting authors by npub)
+ // 2) Check author if you’re blacklisting authors by npub
const authorNpub = this.safeEncodeNpub(video.pubkey) || video.pubkey;
if (initialBlacklist.includes(authorNpub)) {
return false;
@@ -760,6 +914,15 @@ class bitvidApp {
this.renderVideoList(filteredVideos);
});
+
+ // *** IMPORTANT ***: Unsubscribe once we get the historical EOSE
+ // so that we do not hold an open subscription forever:
+ if (this.videoSubscription) {
+ this.videoSubscription.on("eose", () => {
+ this.videoSubscription.unsub();
+ console.log("[loadVideos] unsubscribed after EOSE");
+ });
+ }
} else {
// Already subscribed: just show what's cached
const allCached = nostrClient.getActiveVideos();
@@ -794,10 +957,10 @@ class bitvidApp {
return olderMatches.length > 0;
}
- // 4) Build the DOM for each video in newestActive
async renderVideoList(videos) {
if (!this.videoList) return;
+ // Check if there's anything to show
if (!videos || videos.length === 0) {
this.videoList.innerHTML = `
@@ -809,13 +972,14 @@ class bitvidApp {
// Sort newest first
videos.sort((a, b) => b.created_at - a.created_at);
- // <-- NEW: Convert allEvents map => array to check older overshadowed events
+ // Convert allEvents to an array for checking older overshadowed events
const fullAllEventsArray = Array.from(nostrClient.allEvents.values());
+ const fragment = document.createDocumentFragment();
- const htmlList = videos.map((video, index) => {
+ videos.forEach((video, index) => {
if (!video.id || !video.title) {
console.error("Video missing ID/title:", video);
- return "";
+ return;
}
const nevent = window.NostrTools.nip19.neventEncode({ id: video.id });
@@ -829,32 +993,31 @@ class bitvidApp {
: "border-none";
const timeAgo = this.formatTimeAgo(video.created_at);
- // 1) Do we have an older version?
+ // Check if there's an older version (for revert button)
let hasOlder = false;
if (canEdit && video.videoRootId) {
hasOlder = this.hasOlderVersion(video, fullAllEventsArray);
}
- // 2) If we do => show revert button
const revertButton = hasOlder
? `
-
- `
+
+ `
: "";
- // 3) Gear menu
+ // Gear menu (only shown if canEdit)
const gearMenu = canEdit
? `