Building a PWA Template: structure, styling and core UI
This is the first part of a series detailing the creation of a generic Progressive Web Application (PWA) template. The goal is to build a reusable foundation packed with common features needed for modern web apps. This part focuses on the foundational elements: HTML structure, CSS styling, core application logic, local storage, and basic UI components.
HTML structure
The application uses two main HTML files: index.html for the main interface and help/index.html for a separate help page. Both leverage Bootstrap 5 for layout and core components.
index.html sets up the primary view:
- Offcanvas Sidebar: A collapsible sidebar (
#offcanvasSidebar) for file management (listing files, add/rename/delete buttons). -
Main Content Area: Contains the header with controls and the primary content display area.
- Header: Includes a button to toggle the sidebar, the current file name (
#currentFileNameHeader), a language switcher, sync status indicator, Dropbox button, and help link. - Content Placeholder: An area (
#main-content-area) for application-specific UI, pre-filled with examples of the template’s UI components.
- Header: Includes a button to toggle the sidebar, the current file name (
- Modals: Bootstrap modals for user interactions (add/rename/delete files, sync conflicts).
<!-- Snippet from index.html Header -->
<div class="pt-3 pb-2 mb-3 border-bottom d-flex justify-content-between align-items-center flex-wrap">
<div class="d-flex align-items-center me-3 mb-2 mb-md-0">
<button class="btn btn-light me-3" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasSidebar">...</button>
<h1 class="h2 mb-0" id="currentFileNameHeader" data-i18n="main.header.currentFile">Current File</h1>
</div>
<div class="d-flex align-items-center">
<!-- Language Dropdown -->
<div class="dropdown me-2">...</div>
<!-- Sync Status -->
<span id="syncStatusIndicator" class="me-2 text-muted small"></span>
<!-- Dropbox Button -->
<button type="button" id="dropboxAuthButton" class="btn btn-light p-1 btn-fa me-2">...</button>
<!-- Help Link -->
<a href="help/" class="btn btn-light btn-fa p-1">...</a>
</div>
</div>
This structure provides a clean and adaptable base for various PWA applications.
CSS styling
Styling relies heavily on Bootstrap 5. Customizations are added via:
TEMPLATE.css: Contains general overrides, theme colors (primary#0083B3, complementary#FF4030), button styling, layout adjustments, and styles for the file list sidebar and Dropbox button. It also includes a simple mechanism to prevent Flash of Unstyled Content (FOUC).- Component CSS (
assets/css/ui/,assets/css/notif.min.css): Minified CSS for the datepicker, switch, and notification toasts.
/* Example Theme Variables in TEMPLATE.css */
.btn-primary {
--bs-btn-color:#FFF;
--bs-btn-bg:#0083B3;
--bs-btn-border-color:#0083B3;
/* ... hover, active, disabled states ... */
}
.btn-complementary {
--bs-btn-color: #FFF;
--bs-btn-bg: #FF4030;
--bs-btn-border-color: #FF4030;
/* ... hover, active, disabled states ... */
}
/* FOUC Prevention */
body {
opacity: 0; /* Initially hidden */
transition: opacity 0.4s ease-in-out;
}
body.localized {
opacity: 1; /* Visible once i18next is ready */
}
The styling aims for a clean, modern look that’s easily customizable.
JavaScript implementation: core logic and storage
The application logic is modularized for maintainability.
Core application logic
This script acts as the main entry point for UI interactions.
- Initialization: Calls
initializeDropboxSync()(covered in Part 2) and sets up listeners for file management buttons. - Modal Handling: Manages the opening of Bootstrap modals for file operations, populating necessary data and initializing event listeners dynamically.
Storage system
Handles data persistence using localStorage and file management logic.
-
storage.js: Provides low-level access tolocalStorage. Manages:- A list of known files (
knownFiles). - The currently active file (
activeFile). - Content and metadata for each file using dynamic keys.
- Ensures a default file exists.
- Dispatches a
localDataChangedevent on save.
- A list of known files (
-
files.js: Implements higher-level file operations triggered by the UI.- Updates the file list UI in the sidebar.
- Handles adding, renaming, and deleting files locally and initiates corresponding Dropbox actions.
// Simplified storage structure in localStorage
// knownFiles: [{"name": "default.txt", "path": "/default.txt"}, ...]
// activeFile: "/default.txt"
// content_/default.txt: "File content here"
// lastModified_/default.txt: 1678886400000
// lastSync_/default.txt: 1678886400000
JavaScript implementation: UI components
Reusable UI components enhance the user experience.
datepicker.js: Initializes the Bootstrap Datepicker on.date-pickerelements.switch.js: Initializes Bootstrap switches, setting labels based on state anddata-checked/data-uncheckedattributes.notif.js: Provides functions to show notifications and contains logic to initialize switches with i18n support (more on i18n in Part 2).notif-flash.min.js: Displays notifications based on URL parameters and defines the globalshowNotificationfunction for Bootstrap Toasts.
// Example: Initializing a datepicker
$('.date-picker').datepicker({
format: 'yyyy-mm-dd',
autoclose: true,
// ... other options
});
// Example: Showing a notification
showNotification('File saved successfully!', 'success');
You can access the full source code, at the GitHub repository here.
For more insights into this topic, you can find the details here.