- Type: Progressive Web App (PWA) - Vanilla HTML/CSS/JS
- Purpose: Mobile-first camera recording viewer
- Hosting: https://camera.navynui.cc
- Data Source: data.json (camera recordings metadata)
/home/nui/dev/camera/
├── index.html # Main gallery view with thumbnails & video modal
├── script.js # Core logic (data loading, rendering, video player)
├── style.css # Styling (gallery + video modal + fullscreen)
├── sw.js # Service worker for PWA offline support
├── manifest.json # PWA manifest (also inlined in index.html)
├── icon.svg # App icon
├── data.json # Camera recordings metadata
├── Agents.md # This file
└── README.md # User documentation
# Python 3
python3 -m http.server 8000
# Node.js with serve
npx serve .
# PHP
php -S localhost:8000Then open http://localhost:8000
This is a vanilla JS project - no build, lint, or test commands exist.
- No npm/yarn/pnpm
- No TypeScript
- No linting (ESLint, etc.)
- No test framework
Use Chrome DevTools:
- Application > Service Workers - verify SW registration
- Lighthouse - run PWA audit
- Application > Manifest - verify PWA metadata
Variables & Constants
- Use
varfor global state (legacy style in this codebase) - Use
constfor constants:const PAGE_SIZE = 12; - Use
letfor local variables
Functions
- Use function declarations:
function functionName() {} - Keep functions small and focused
- Document complex logic with inline comments
Naming Conventions
- camelCase for variables and functions:
jsonD,loaddata(),currentVideoIndex - All caps for constants:
PAGE_SIZE - Descriptive names:
currentVideoIndexnotidx
Code Structure
// Global state (top of file)
var jsonD = [], menu = [];
// Constants
const PAGE_SIZE = 12;
// Functions (alphabetical or logical grouping)
function init() {}
function loadData() {}
function render() {}
function handleEvent() {}
// Event listeners (bottom)
document.addEventListener("DOMContentLoaded", function() {});Error Handling
- Use try/catch for iframe detection:
try { ... } catch (e) { ... } - Add
.catch()to fetch promises - Check DOM elements exist before use:
if (mn) mn.innerHTML = ""
No TypeScript
- This is a vanilla JS project - do not add TypeScript
- If types needed, use JSDoc comments
Structure
- Use semantic HTML5 elements
- Keep inline styles minimal (use style.css)
- External scripts with version query:
script.js?v=mobile_v8
Meta Tags
- Viewport:
<meta name="viewport" content="width=device-width, initial-scale=1"> - Theme color:
<meta name="theme-color" content="#000000"> - PWA: Include both
mobile-web-app-capableandapple-mobile-web-app-capable
Variables
- Define in
:root:--primary: #00d1b2; - Use throughout:
color: var(--primary);
Formatting
- Use 2-space indentation
- Group related styles
- Comment sections:
/* Section Name */
Responsive
- Use Bulma classes for grid:
is-one-quarter-widescreen is-half-tablet - Add custom media queries:
@media screen and (max-width: 768px) {}
- SVG for icons:
icon.svg - Inline manifest in HTML as data URI for PWA
- Keep favicon references updated
- New JS Function: Add to script.js following naming conventions
- New CSS: Add to style.css with variables
- New HTML: Add to index.html, keep inline styles minimal
- New Data: Update data.json format if needed
When modifying, ensure:
- Service worker registered in sw.js
- Manifest includes icon (inline in HTML)
- Theme color matches design
- Works offline (network-first or cache-first strategy)
- Page loads without console errors
- Thumbnails render from data.json
- Click thumbnail opens video modal
- Video controls work (play/pause/seek/volume)
- Fullscreen works (button, double-click, F key)
- Next/Prev video navigation works
- Keyboard shortcuts work
- PWA installable (Lighthouse audit)
- Works on mobile viewport