<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Podcast Episode Repository</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* Minimal, beautiful, and functional styling following Human Interface Guidelines */
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
background-color: #f9f9f9;
color: #333;
}
header {
background-color: #fff;
padding: 20px;
text-align: center;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
header h1 {
margin: 0;
font-size: 24px;
}
main {
max-width: 800px;
margin: 40px auto;
padding: 0 20px;
}
.upload-section {
background-color: #fff;
padding: 30px;
border-radius: 8px;
text-align: center;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.upload-button {
display: inline-block;
padding: 10px 20px;
margin-bottom: 15px;
font-size: 16px;
color: #fff;
background-color: #007aff;
border-radius: 6px;
cursor: pointer;
text-decoration: none;
}
.episode-list {
margin-top: 40px;
}
.episode {
background-color: #fff;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.episode h2 {
margin-top: 0;
font-size: 18px;
}
.episode audio {
width: 100%;
margin-top: 10px;
}
.no-episodes {
text-align: center;
color: #777;
font-size: 18px;
margin-top: 20px;
}
.select-folder-button {
display: inline-block;
padding: 10px 20px;
margin-bottom: 15px;
font-size: 16px;
color: #fff;
background-color: #28a745;
border-radius: 6px;
cursor: pointer;
text-decoration: none;
}
.folder-path {
font-size: 14px;
color: #555;
}
</style>
</head>
<body>

<header>
<h1>My Podcast Episodes</h1>
</header>

<main>
<section class="upload-section">
<div id="folder-selection">
<a href="#" class="select-folder-button" id="select-folder-button">Select Repository Folder</a>
</div>
<div id="folder-info" style="display:none;">
<p class="folder-path" id="folder-path"></p>
<a href="#" class="upload-button" id="upload-button">Upload .wav File</a>
</div>
</section>

<section class="episode-list" id="episode-list">
<!-- Episodes will be dynamically added here -->
</section>
</main>

<script src="https://unpkg.com/@tauri-apps/api@latest/dist/index.iife.js"></script>
<script>
(function() {
const { dialog, fs, path, tauri } = window.TAURI;

text
const selectFolderButton = document.getElementById('select-folder-button');
const uploadButton = document.getElementById('upload-button');
const folderPathDisplay = document.getElementById('folder-path');
const folderSelectionDiv = document.getElementById('folder-selection');
const folderInfoDiv = document.getElementById('folder-info');
const episodeList = document.getElementById('episode-list');

let repoFolderPath = null;

// Load repository folder path from local storage on startup
document.addEventListener('DOMContentLoaded', async () => {
  const storedPath = localStorage.getItem('repoFolderPath');
  if (storedPath) {
    repoFolderPath = storedPath;
    await initRepository();
  } else {
    // Show select folder button
    folderSelectionDiv.style.display = 'block';
    folderInfoDiv.style.display = 'none';
  }
});

selectFolderButton.addEventListener('click', async () => {
  const selected = await dialog.open({ directory: true });
  if (selected) {
    repoFolderPath = selected;
    // Save the repo folder path to localStorage
    localStorage.setItem('repoFolderPath', repoFolderPath);
    await initRepository();
  }
});

async function initRepository() {
  folderPathDisplay.textContent = `Repository Folder: ${repoFolderPath}`;
  folderSelectionDiv.style.display = 'none';
  folderInfoDiv.style.display = 'block';
  await loadEpisodes();
}

uploadButton.addEventListener('click', async () => {
  const selectedFiles = await dialog.open({
    filters: [{ name: 'Audio Files', extensions: ['wav'] }]
  });

  if (selectedFiles) {
    const files = Array.isArray(selectedFiles) ? selectedFiles : [selectedFiles];
    for (const filePath of files) {
      try {
        const fileName = await path.basename(filePath);
        // Copy the file to the repository folder
        const destination = await path.join(repoFolderPath, fileName);
        await fs.copyFile(filePath, destination);
        addEpisodeToList({ name: fileName, path: destination });
      } catch (error) {
        console.error('Error copying file:', error);
      }
    }
  }
});

// Load episodes from the repository folder
async function loadEpisodes() {
  episodeList.innerHTML = ''; // Clear the list
  try {
    const entries = await fs.readDir(repoFolderPath);
    if (entries.length === 0) {
      showNoEpisodesMessage();
    } else {
      for (const entry of entries) {
        if (!entry.children && entry.name.endsWith('.wav')) {
          addEpisodeToList({ name: entry.name, path: entry.path });
        }
      }
    }
  } catch (error) {
    console.error('Error reading directory:', error);
  }
}

// Add episode to the episode list in the UI
function addEpisodeToList(episode) {
  removeNoEpisodesMessage();

  const episodeElement = document.createElement('div');
  episodeElement.className = 'episode';

  const title = document.createElement('h2');
  title.textContent = episode.name;
  episodeElement.appendChild(title);

  const audio = document.createElement('audio');
  audio.controls = true;

  // Create a file URL for the audio file
  audio.src = tauri.convertFileSrc(episode.path);

  episodeElement.appendChild(audio);

  episodeList.appendChild(episodeElement);
}

// Show a message when there are no episodes
function showNoEpisodesMessage() {
  const message = document.createElement('p');
  message.className = 'no-episodes';
  message.textContent = 'No episodes added yet.';
  episodeList.appendChild(message);
}

// Remove the no episodes message
function removeNoEpisodesMessage() {
  const message = document.querySelector('.no-episodes');
  if (message) {
    message.remove();
  }
}
})();
</script>

</body>
</html>

Transform this code into an obsidian clone. Keep it in a single file. Again, first time opening the app ask me for selecting a folder / vault… then, each note i create it's stored in that folder as .txt, the saving it's automatically.