- Updated Amber login button to reflect new three-phase process.
- Added handling for reading public key and signature from clipboard.
- Introduced new state management for Amber login phases.
- Enhanced user feedback during each phase with appropriate messaging.
- Refactored related functions for clarity and maintainability.
- "Go back" replaced with red italic "fuck you, I wanna be lame"
- After dismissing, sovereign trap no longer intercepts clicks
- Form fields become real inputs (email/password) for actual use
- sovereignDismissed state resets when modal reopens or closes
Co-authored-by: Cursor <cursoragent@cursor.com>
Cards now scale to match the Algos grid proportions at each breakpoint
(1/3, 1/4, 1/5, 1/6 of viewport) while remaining in a horizontally
scrolling flex row with nav buttons on desktop.
Co-authored-by: Cursor <cursoragent@cursor.com>
ContentRow and Browse My List sections now use a responsive CSS grid
instead of fixed-width cards in a horizontal scroll:
- Mobile: 2 columns grid
- md (768px): 3 columns
- lg (1024px): 4 columns
- xl (1280px): 5 columns
- 2xl (1536px): 6 columns
Cards fill the available width at every breakpoint, matching the
Algos/Trending tab grid layout for visual consistency.
Scroll nav buttons hidden on desktop (grid doesn't scroll).
Co-authored-by: Cursor <cursoragent@cursor.com>
The filter grid was using md:grid-cols-3 (3 cards) while Films
horizontal rows showed 6. Updated to md:4 lg:5 xl:6 so both
views scale consistently across breakpoints.
Co-authored-by: Cursor <cursoragent@cursor.com>
Cards were feeling too large at 5 per row. Updated calc to fit 6
cards uniformly across ContentRow and Browse (My List sections).
Co-authored-by: Cursor <cursoragent@cursor.com>
Root cause: HLS content is AES-128 encrypted, but the key endpoint
required mandatory auth (HybridAuthGuard). HLS.js fetches the key
without auth headers, causing a silent 401 and playback failure.
Backend:
- Changed key.controller.ts to use OptionalHybridAuthGuard
- Free content (price <= 0) now serves keys without authentication
- Paid content still requires auth, returns 401 for anon requests
- Added Content entity injection to look up pricing
Frontend:
- Configured HLS.js xhrSetup to attach Bearer token on /key requests
- Uses nostr_token or auth_token from sessionStorage
- Ensures logged-in users can play paid encrypted content
Co-authored-by: Cursor <cursoragent@cursor.com>
- NAH! text now slides in from the left with a scale punch and glow
- Own your privacy phase slides in from the left with a smooth fade
- Close button restyled to match ContentDetailModal (circular, glassmorphism, blur)
Co-authored-by: Cursor <cursoragent@cursor.com>
- Modal now opens in register mode by default instead of login
- Removed the subtitle text under the heading
- Fake form fields update based on mode (Create a password vs Enter)
- Toggle text reads "Already have an account? Sign in" first
- Forgot password only shows in login mode
Co-authored-by: Cursor <cursoragent@cursor.com>
When users click on the legacy email/password form, the form zooms
out and a bold "NAH!" animates in. This transitions to an
"Own your privacy" message with a "Generate Sovereign Identity"
button that creates a new Nostr keypair, logs the user in, and
presents a red glassmorphism "Download your new identity" button
that saves the nsec/npub keypair to a text file.
Uses applesauce PrivateKeyAccount.fromKey() for proper account
registration and persistence.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replaced the hero-info-button class with a dark glass morphism style
matching the nav buttons — dark translucent background, subtle inset
highlight, backdrop blur, and hover lift. Added an -or- divider
between the Nostr Extension and Amber login options.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the flat #141414 grey background with a dark glass container
matching the header's floating-glass style — rgba(6,6,6,0.92) with
backdrop-filter blur, subtle white/6% border, and layered shadows.
Updated the hero gradient to blend seamlessly into the new base.
Co-authored-by: Cursor <cursoragent@cursor.com>
Reordered the right-side header actions so the search icon appears
before the Sign In button when the user is not authenticated.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Stream endpoint now accepts both content ID and project ID,
falling back to project lookup when content ID is not found
- Added /contents/:id/stream-debug diagnostic endpoint that checks
file existence in both private and public MinIO buckets
- Stream endpoint now verifies raw file exists before generating
presigned URL, returning a clear error if file is missing
- Added comprehensive logging throughout the stream pipeline
- VideoPlayer now logs stream URL, API responses, and playback errors
to browser console for easier debugging
- Bumped CACHEBUST for frontend (19), API (11), and ffmpeg-worker (13)
Co-authored-by: Cursor <cursoragent@cursor.com>
Cards used a fixed 280px width which showed ~6 on most desktops.
Algorithm filter tabs used a 5-column grid. This mismatch caused
layout jumping when switching tabs.
Now uses calc((100vw - 12rem) / 5) so exactly 5 cards are visible
on desktop for all scroll rows (Films, My List, Rentals, etc.),
matching the 5-column grid in filter views. Mobile stays at 200px.
Co-authored-by: Cursor <cursoragent@cursor.com>
Mobile browsers block navigator.clipboard.readText() unless called
inside a user gesture (tap/click). The old flow relied on the
visibilitychange event to auto-read the clipboard when the user
returned from Amber, which silently failed.
New flow:
1. User taps "Sign in with Amber" → opens Amber via Android intent
2. User approves in Amber → pubkey copied to clipboard
3. User returns to browser → sees "Complete Sign-in" button
4. User taps "Complete Sign-in" → clipboard read succeeds (user gesture)
5. Pubkey decoded, account registered, backend session created
Also handles npub/nprofile decoding and provides clear error messages
for empty clipboard, missing permissions, and non-Android devices.
Co-authored-by: Cursor <cursoragent@cursor.com>
The filmmakerService.usesSelfHosted() was tied to the content source
toggle, returning true only for 'indeehub-api'. When the user switched
to 'topdocfilms' or 'indeehub', the mergePublishedFilmmakerProjects()
function routed filmmaker API calls to the wrong (external) API, so
backstage-created films never appeared.
Now in production (USE_MOCK=false), filmmaker operations always use
the self-hosted backend regardless of which content catalog is active.
The content source toggle only affects the browse page catalog display.
Co-authored-by: Cursor <cursoragent@cursor.com>
vue-tsc flagged variables as unused since their template references are
inside HTML comments. Prefix with underscores and comment out the
related functions/imports so the production build passes cleanly.
Co-authored-by: Cursor <cursoragent@cursor.com>
These are dev/testing tools that shouldn't be visible in production.
Commented out for now so they can be re-enabled easily.
Co-authored-by: Cursor <cursoragent@cursor.com>
The rental check catch block was incorrectly setting hasActiveRental=true
for project owners when the API call failed (e.g. auth token not synced).
This showed a "Rented" badge with no time remaining and hid the rent button.
- Separate "owner can play" from "has active rental" via new isOwner computed
- canPlay now includes isOwner so owners always have playback access
- Catch block no longer fakes a rental — keeps the badge accurate
- New purple "Your project" badge for owners (distinct from green "Rented")
Co-authored-by: Cursor <cursoragent@cursor.com>
- Modified Nginx configuration to trust the outer reverse proxy's X-Forwarded-Proto header, enhancing protocol handling.
- Updated initMockMode function in mock.ts to use the backend health endpoint for improved error handling and timeout management, ensuring a more robust fallback to mock data when the backend is unreachable.
- Modified baseURL and cdnURL in api.config.ts to include VITE_INDEEHUB_API_URL, enhancing the ability to switch between different API endpoints.
- Updated initMockMode function in mock.ts to reflect the changes in API URL handling, ensuring consistency across the application.
- Revised .env.portainer to update sensitive credentials and streamline comments for clarity.
- Adjusted docker-compose.yml to remove unnecessary variable references, enhancing readability and maintainability.
- Updated VideoPlayer component to improve type handling and refactor seeking logic for better performance.
- Enhanced library service to include providerId in the rentContent method for improved data handling.
- Refactored auth store to integrate account management functionality.
- Cleaned up ProjectEditor and Settings views by removing unused computed properties and refining method types.
- Updated docker-compose.yml to include environment variable support for services, enhancing flexibility in configuration.
- Refactored Dockerfile to utilize build arguments for VITE environment variables, allowing for better customization during builds.
- Improved Nginx configuration to handle larger video uploads by increasing client_max_body_size to 5GB.
- Enhanced backend Dockerfile to include wget for health checks and improved startup logging for database migrations.
- Added validation for critical environment variables in the backend to ensure necessary configurations are present before application startup.
- Updated content streaming logic to support direct HLS URL construction, improving streaming reliability and user experience.
- Refactored various components and services to streamline access checks and improve error handling during content playback.
- Integrated HLS.js version 1.6.15 into the project for improved video streaming capabilities.
- Updated the ContentsController to check for HLS manifest availability and fall back to presigned URLs for original files if not found.
- Enhanced the VideoPlayer component to handle loading and error states more effectively, improving user experience during streaming.
- Refactored content service methods to return detailed streaming information, including HLS and DASH manifest URLs.
- Updated the BTCPay service to support internal Lightning invoices with private route hints, improving payment routing for users with private channels.
- Added reconciliation methods for pending rents and subscriptions to ensure missed payments are processed on startup.
- Enhanced the rental and subscription services to handle payments in satoshis, aligning with Lightning Network standards.
- Improved the rental modal and content detail components to display rental status and pricing more clearly, including a countdown for rental expiration.
- Refactored various components to streamline user experience and ensure accurate rental access checks.
- Added a new `api` service for the NestJS backend, including health checks and dependencies on PostgreSQL, Redis, and MinIO.
- Introduced PostgreSQL and Redis services with health checks and configurations for data persistence.
- Added MinIO for S3-compatible object storage and a one-shot service to initialize required buckets.
- Updated the Nginx configuration to proxy requests to the new backend API and MinIO storage.
- Enhanced the Dockerfile to support the new API environment variables and configurations.
- Updated the `package.json` and `package-lock.json` to include new dependencies for QR code generation and other utilities.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Updated the `seedComments` function to return an array of published comment event IDs for tracking.
- Introduced `seedCommentReactions` to seed upvotes and downvotes on comments, improving interaction visibility.
- Enhanced the `App.vue` and `MobileNav.vue` components to support a mobile search overlay, allowing users to search films seamlessly.
- Added a new `MobileSearch` component for better search experience on mobile devices.
- Implemented a search feature in `AppHeader.vue` with dropdown results for improved content discovery.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Added new composable `usecontentdiscovery` and `contentsource` to support additional content sources in the application.
- Removed unused `isAmberSupported` from the AuthModal component to streamline the authentication process.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Introduced a new content source toggle in the profile and app header to switch between IndeeHub and TopDoc films.
- Updated the content fetching logic to dynamically load content based on the selected source.
- Enhanced the seeding process to include a combined catalog of IndeeHub and TopDoc films, ensuring diverse content availability.
- Improved user interaction by preventing duplicate reactions and ensuring a smoother voting experience across comments and content.
- Added support for Amber login (NIP-55) for Android users, integrating it into the existing authentication flow.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replaced the grid layout on the algo filter view with the same flex
slider container (gap-8, pt-6 pb-8, fixed card widths) used by
ContentRow and My List, with flex-wrap so all items remain visible.
Co-authored-by: Cursor <cursoragent@cursor.com>
The app had two disconnected auth systems:
- Auth store (useAuth): controls isAuthenticated, subscription, My List
- Account manager (useAccounts): controls isNostrLoggedIn, comments
Previously each login path only populated one system:
- Persona login → Nostr only (no subscription/My List)
- AuthModal Nostr → Auth store only (no commenting)
- Extension login → Nostr only (no subscription/My List)
Now every login path bridges both systems:
- Persona/extension login also calls auth store loginWithNostr
- AuthModal Nostr login also registers extension in accountManager
- Logout already cleared both (no change needed)
Co-authored-by: Cursor <cursoragent@cursor.com>
Two root causes for seeding not working on production:
1. Origin mismatch: The seeder writes content IDs as
http://localhost:7777/content/... but the app was using
window.location.origin (the user's actual browser URL) to
query the relay. Introduced VITE_CONTENT_ORIGIN env var
baked into the Docker build so both sides use the same origin.
2. Dockerfile.seed fragility: Replaced --omit=dev + global tsx
with a cleaner approach that strips sharp from package.json
(the only native dep that fails on Alpine) then does a full
npm install, ensuring tsx/esbuild and all applesauce deps
resolve correctly.
Also improved wait-for-relay to accept any HTTP response (some
relays return 4xx for plain GET) and increased max attempts.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replaced grid layout in My List sections with the same horizontal
scroll slider used by ContentRow: flex gap-8, fixed card widths
(200px/280px), matching padding and overflow behavior. Cards,
spacing, and scrolling now look identical across Films and My List.
Co-authored-by: Cursor <cursoragent@cursor.com>
Title and description text sizes in the My List (Continue Watching,
Saved Films, Rentals) and filtered grid views were smaller than
the Films tab ContentRow cards. Aligned all to use the same
text-base/md:text-xl title and text-base description sizing.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add the same truncated description line to Continue Watching
and My Rentals grids so card sizing matches the other screens.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Wrap inline algo buttons in a hidden/flex container so the
parent div controls visibility instead of per-button classes
(scoped .nav-button display:inline-block was overriding
Tailwind's hidden class)
- Add flex-shrink-0 to logo link so it never gets squeezed out
on narrower desktop screens
- Reduce logo-to-nav gap on md screens (gap-4) to prevent
overflow, widen to gap-10 at lg+
Co-authored-by: Cursor <cursoragent@cursor.com>
- Top-level comments keep their existing layout (avatar, name,
timestamp, text, action bar)
- Replies now render in a rounded glass bubble with subtle
background and border, chat-message style (flat top-left
corner, rounded on the other three)
- Smaller avatars and more compact action buttons for replies
- Reply form pulled outside the comment layout for cleaner
nesting at all depths
- Better spacing between comment threads
Co-authored-by: Cursor <cursoragent@cursor.com>
- Top-level comments render as glass-card bubbles with subtle
border, backdrop blur, and hover highlight
- Replies use a lighter, more compact bubble variant
- Threaded replies connected by a vertical line on the left
instead of raw margin indentation
- Action buttons (upvote, downvote, reply, expand) styled as
pill-shaped micro-buttons inside each bubble
- Reply form nests inline within the parent bubble
- Proper spacing and responsive padding at all nesting depths
Co-authored-by: Cursor <cursoragent@cursor.com>
- Clicking My List when not logged in now opens the auth modal
directly instead of navigating to a page with a sign-in button
- After successful login, auto-redirects to /library (My List)
- Works on both desktop header and mobile tab bar
- App.vue tracks a pending redirect path so the post-login
navigation happens seamlessly
- Direct URL navigation to /library when not logged in also
triggers the modal and redirects back to Films
Co-authored-by: Cursor <cursoragent@cursor.com>
- Replace broken shield SVG in auth modal Nostr login button
with a proper key icon (matches Nostr's key-based identity)
- Show algorithm filter buttons inline on xl+ screens (1280px+)
where there's room for all of them
- Collapse into "Algos" dropdown on md–xl screens to prevent
overflow when the header is too narrow
Co-authored-by: Cursor <cursoragent@cursor.com>
- Replace inline filter buttons in desktop header with a single
"Algos" dropdown that shows all discovery algorithms in a glass
menu with checkmark for the active selection and a clear option
- Button label dynamically shows the active algorithm name or
defaults to "Algos" when no filter is active
- Rename mobile tab bar "Filters" to "Algos" with a gear icon
- Rename bottom sheet title to "Algos" to match
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add nostr-rs-relay service to docker-compose for persistent
comments, reactions, and profiles on the dev server
- Add one-shot seeder container that auto-populates the relay
with test personas, reactions, and comments on first deploy
- Proxy WebSocket connections through nginx at /relay so the
frontend connects to the relay on the same host (no CORS)
- Make relay URL dynamic: reads from VITE_NOSTR_RELAYS in dev,
auto-detects /relay proxy path in production Docker builds
- Make seed scripts configurable via RELAY_URL and ORIGIN env vars
- Add wait-for-relay script for reliable container orchestration
- Add "Resume last played" hero banner on My List tab
Co-authored-by: Cursor <cursoragent@cursor.com>
- Added several new dependencies related to the Applesauce library, including 'applesauce-accounts', 'applesauce-common', 'applesauce-core', 'applesauce-loaders', 'applesauce-relay', and 'applesauce-signers', all at version 5.1.0.
- Updated the development script in package.json to specify a port for Vite and added new seed scripts for profiles and activity.
- Removed outdated image files from the public directory to clean up unused assets.
- Enhanced the App.vue structure by integrating shared components like AppHeader and AuthModal for improved user experience.
- Refactored ContentDetailModal and MobileNav components to support new features and improve usability.
These changes improve the overall functionality and maintainability of the application while ensuring it utilizes the latest libraries for better performance.
- Added detailed labels to the deployment script for IndeedHub, including title, version, description, license, icon, and repository URL.
- Updated package dependencies in package.json and package-lock.json, including upgrading 'nostr-tools' to version 2.23.0 and adding 'axios' and '@tanstack/vue-query'.
- Improved README with a modern description of the platform and updated project structure details.
This commit enhances the clarity of the deployment process and ensures the project is using the latest dependencies for better performance and features.