Skip to content

Repository files navigation

AntechEvents AntechEvents

Your personal event command center — capture events, keep every link handy, schedule with confidence, and catch conflicts before they bite.

HTML5 Tailwind CSS JavaScript Firebase Firebase Hosting

AntechEvents is a fast, framework-free multi-page app for tracking the events you're planning or attending. It's built with semantic HTML5, compiled Tailwind CSS, modern vanilla JavaScript (ES modules), Firebase Authentication, and Cloud Firestore — no React/Vue/Angular, no bundler, no runtime CSS-in-JS. Each page is served at a clean, extensionless URL (/dashboard, not /dashboard.html).


Contents Table of Contents


Overview Overview

The goal is a calm, focused place to manage personal events without the friction of a full calendar suite. AntechEvents brings together:

  • a dashboard that answers "what's next?" at a glance
  • an agenda grouped by day, with search, status filters, and time scopes
  • one create/edit form with a live conflict preview
  • deterministic overlap detection so you never double-book by accident
  • a free/busy availability view with manually blocked busy periods
  • shareable free/busy links with owner-approved meeting requests
  • per-user data, private by default and enforced by Firestore security rules
  • automatic sign-out after five minutes without activity, shared across open tabs

Every screen handles its loading, empty, filtered-empty, validation, and error states explicitly, and the whole UI is built mobile-first with accessibility as a baseline.


Release Latest Release

v1.1.0 — Progressive Web App

AntechEvents is now an installable Progressive Web App. Add it to your device, launch it full-screen, keep using pages you've already opened when your connection drops, and get reminded on your device before events start — all with no backend and nothing to pay for.

  • Install to your device — standalone, full-screen on mobile and desktop, with a contextual install prompt that only appears once you actually have events.
  • Works offline — visited pages stay available without a connection, with a clean offline screen and a "Try again" action for everything else.
  • Device reminders — opt in from Settings for real notifications before an event starts (while a tab is open). Titles and times only, never notes or location.
  • Safe updates — an unobtrusive banner lets you update on your terms; it never reloads mid-interaction.
  • Connectivity awareness — a subtle indicator when you go offline and come back, with no surprise retries of failed actions.

Auth and Firestore responses are never cached, no secrets ship to the browser, and every capability is feature-detected — on unsupported browsers AntechEvents runs as a normal website. Background push while the app is fully closed remains out of scope (it needs a server to send it); the groundwork is in place to add it later without a rewrite. See Progressive Web App for the technical detail.


Features Core Features

1. Landing experience

A public landing page (/) introducing the product, with clear calls to action into sign-up and log-in. Authenticated visitors are sent straight to their dashboard.

2. Dashboard

The central experience (/dashboard): a time-of-day greeting, today's counts, your next event, upcoming events, schedule conflicts, an availability summary, and quick actions.

3. Events agenda

An agenda (/events) grouped by day, with full-text search across title, location, and organizer, status filters, and an upcoming / all / past time scope.

4. Create & edit

One form (/createevent, ?id= to edit) for both creating and editing, with inline validation, progressive disclosure for optional details, a live conflict preview, and a smart default end time drawn from your preferences.

5. Event detail & actions

A detail view (/event?id=…) with every action: edit, duplicate, mark confirmed / attended, cancel, restore, open link, copy link, and delete behind an accessible confirmation.

6. Availability

A per-day free/busy view (/availability) with manually blocked busy periods, a month calendar for navigation, and a weekly summary.

Shareable links. Generate a capability link that shows others only your busy/free times — never event titles or details. Per link, choose whether visitors may leave a note or propose a meeting; proposals arrive as pending requests you approve, and accepting one creates the event. Links need no sign-in to view and are revocable at any time.

7. Settings

Account name, scheduling preferences (timezone, week start, default duration and reminder), and notification choices (/settings).

8. Accessible by default

Semantic landmarks, keyboard-navigable menus and modals with focus trapping, visible focus rings, aria-live toasts, and status communicated with icon + text — never color alone.


Structure Project Structure

Each page lives in its own folder as index.html, so Hosting (and the local dev server) serves it at a clean, extensionless path. Every asset and navigation reference is root-absolute (/css, /js, /dashboard) so links resolve identically no matter how deep the current URL is.

.
├── index.html                  # Landing page              →  /
├── login/index.html            # Auth screens              →  /login
├── register/index.html         #                           →  /register
├── dashboard/index.html        # Central product experience →  /dashboard
├── events/index.html           # Agenda list               →  /events
├── event/index.html            # Event detail              →  /event?id=…
├── createevent/index.html      # Create / edit form        →  /createevent (?id= to edit)
├── availability/index.html     # Free/busy + month calendar →  /availability
├── share/index.html            # Public shared free/busy    →  /share?token=…
├── settings/index.html         # Account, preferences       →  /settings
├── css/
│   ├── input.css               # Tailwind entry: @theme tokens + component classes
│   └── output.css              # Compiled stylesheet (committed; regenerate on change)
├── js/
│   ├── firebase.js             # SDK init + single re-export surface
│   ├── app.js                  # Auth-guarded shell bootstrap (initShell)
│   ├── auth.js                 # Sign in / up / out, guards, redirect safety
│   ├── navigation.js           # Header + mobile tab bar + account menu
│   ├── ui.js                   # Icons, toasts, modals, badges, state placeholders
│   ├── eventcard.js            # Reusable event card
│   ├── conflicts.js            # Deterministic overlap detection
│   ├── reminders.js            # Reminder timing + inert delivery boundary
│   ├── eventinbox.js           # Prepared Event Inbox boundary (disabled)
│   ├── <page>.js               # One controller per page (dashboard.js, events.js, …)
│   ├── share.js                # Public share page controller (no auth)
│   ├── services/               # Firestore data access (events, users, availability, shares)
│   └── utils/                  # dates, intervals, formatters, validation, storage, token
├── assets/icons/favicon.svg
├── firebase/
│   ├── firestore.rules         # Per-user ownership rules
│   └── firestore.indexes.json  # Composite indexes (events, availability)
├── firebase.json               # Hosting + Firestore config
└── package.json

Layering: pages render and wire only; all Firestore access lives in js/services/*; pure logic (dates, formatting, validation, conflicts) has no Firebase or DOM dependency and is trivially testable in isolation.

The root-level index.html, manifest.json, sw.js, and offline.html are web/PWA entry points that must stay at the site root. package.json, its lockfile, and hosting configuration also stay at the root because npm and the hosting providers resolve them there. Other application code, styles, assets, and route pages are already grouped in their respective folders.


Stack Tech Stack

Logo Technology
HTML5 HTML5 — semantic markup, one folder-per-page route
Tailwind CSS Tailwind CSS v4 — compiled to css/output.css (no CDN)
JavaScript JavaScript — vanilla ES modules, one entry module per page
Firebase Auth Firebase Authentication — email/password + Google
Cloud Firestore Cloud Firestore — per-user ownership enforced by security rules
Firebase Hosting Firebase Hosting — clean, extensionless URLs

There is no build step for JavaScript — modules are served as-is and import the Firebase SDK from Google's pinned CDN. The only compile step is Tailwind → CSS.


Getting started Getting Started

You'll need Node 18+. The repo is wired to a Firebase project called antechevent; point it at your own by editing the config in js/firebase.js.

1. Clone and enter the project

git clone <repository-url> antechevents
cd antechevents

2. Install dev dependencies

npm install

Dependencies are dev-only: the Tailwind CLI and a static file server. The app ships no runtime npm dependencies.

3. Compile the stylesheet

npm run build:css     # compile css/input.css → css/output.css (minified)

Run Running the Project

npm run serve         # static server at http://localhost:5173

The local server resolves clean URLs the same way Hosting does — /dashboard serves dashboard/index.html — so what you see locally matches production.

There's no JavaScript build step; modules load the Firebase SDK from Google's pinned CDN, so the only thing that compiles is the stylesheet. While working, run the watcher in a second terminal to rebuild CSS on save:

npm run watch:css     # or: npm run dev
Script What it does
npm run build:css One-off Tailwind compile to css/output.css (minified)
npm run watch:css Rebuild css/output.css on every change
npm run serve Serve the project at http://localhost:5173
npm run dev Alias for watch:css

Firebase Firebase Setup

The web config in js/firebase.js is committed. These values aren't secrets — Firestore rules do the enforcing — so they're safe to ship to the browser. To back the app with your own project:

  1. Authentication → Sign-in method — enable Email/Password and Google.

  2. Authentication → Settings → Authorized domains — add localhost and your Firebase Hosting domain.

  3. Firestore Database — create one in production mode.

  4. Deploy the security rules and composite indexes:

    firebase deploy --only firestore:rules,firestore:indexes

Rules and indexes live in firebase/. The composite indexes backing the ownerId + startAt queries (events and availability) are declared in firebase/firestore.indexes.json, so they deploy with the command above — no manual index creation in the console required.


Data Data Model

Four collections, each scoped to its owner by ownerId:

Collection Contents
users/{uid} Profile and scheduling/notification preferences.
events/{eventId} A single event and its status.
availability/{docId} A manually blocked busy period.
shares/{token} A public free/busy link: label, timezone, permission flags, revoke state, and a snapshot of merged busy times.

An event document holds:

title, description, startAt, endAt, timezone, location, eventUrl,
registrationUrl, organizer, notes, status, reminderSettings,
ownerId, createdAt, updatedAt

status is one of planned, registered, confirmed, attended, or cancelled. Dates persist as Firestore Timestamps and are converted to Date at the service layer — nothing above js/services/ ever touches a Timestamp.

Shareable availability

A shares/{token} document's id is an unguessable capability token. It stores only a denormalized snapshot of merged busy time ranges (start/end timestamps) plus an owner-chosen label, timezone, and the allowNotes / allowProposals / revoked flags — no event titles, locations, or counts. Visitors' notes and meeting proposals live in a shares/{token}/submissions/{subId} subcollection:

type (note|proposal), name, email, message, proposedStart?, proposedEnd?, status, createdAt

The public /share page reads a single non-revoked share by token — it can't list or enumerate links, and the private events / availability collections are never exposed. Proposals are created with status: pending and never touch the calendar until the owner accepts one, which creates a normal event.

Security rules

firebase/firestore.rules locks every document to its owner: reads and writes require request.auth.uid == resource.data.ownerId, and new events must carry the caller's ownerId and a non-empty title. The one public surface is a non-revoked shares/{token} document (busy/free times only); a visitor may create a submissions entry only when the link permits it, and the rules validate every field and size. Listing shares is denied to the public, so links can't be enumerated. The client-side checks are there for a clean UX; the rules are the real authorization boundary.


Conflicts Conflict Detection

Two active events conflict when their intervals overlap:

startA < endB && endA > startB

Cancelled events are ignored. If two events fall on the same day but one is missing an end time, they're reported as a possible conflict rather than a definite one. The logic lives in js/conflicts.js and has no Firebase or DOM dependency.


Integrations Deferred Integrations

Two features are scaffolded behind boundaries so they can land later without touching the core app:

  • Event Inbox (js/eventinbox.js) — paste a link, have a backend extract the details, review the draft, save. Nothing runs client-side yet; the module returns an empty draft shaped like the create form. Flip EVENT_INBOX_ENABLED once the backend exists.
  • Email reminders (js/reminders.js) — reminder timing is computed on the client, but delivery is a no-op. A backend (a Cloud Function, say) will read due reminders and call Resend. That key stays on the backend and never reaches the browser.

PWA Progressive Web App

AntechEvents is installable and works offline for pages you've already opened.

  • Manifest + icons — manifest.json (standalone, portrait, brand theme) with the existing SVG mark plus a maskable variant.
  • Service worker (sw.js) — versioned caches (antechevents-static-*, antechevents-runtime-*); network-first for navigations, stale-while-revalidate for static assets, and an offline.html fallback. Auth and Firestore responses are never cached. Bump VERSION to invalidate old caches.
  • Registration + updates (js/pwa.js) — registers the worker on every page and shows an unobtrusive "Update" banner when a new version is waiting; the reload only happens on click, never mid-interaction.
  • Install prompt (js/installprompt.js) — contextual, shown on the dashboard only after the user has events, and dismissable (persisted locally).
  • Device reminders (js/notificationpermission.js) — opt-in from Settings. Due reminders surface as real OS notifications via the service worker while a tab is open — free, no backend. Titles + times only, never notes or location. Background push while the app is fully closed is out of scope: it requires a server to send Web Push/FCM with credentials that can't ship to the browser. The service worker keeps an inert push handler ready for that future backend, but no FCM SDK or token code ships today.
  • Network status (js/networkstatus.js) — a subtle, announced online/offline indicator; never auto-retries failed writes.

Every capability is feature-detected: on unsupported browsers AntechEvents runs as a normal web app.

Session timeout

Authenticated pages sign the user out after five minutes without keyboard, pointer, touch, scroll, click, or form input activity. Activity is shared across tabs in the same browser, and the timeout is rechecked when a background tab becomes active again.


Design Design & Conventions

  • No frameworks, no inline styles, no inline event handlers. Behavior is wired with addEventListener from ES modules.
  • Filenames are lowercase with no dashes (createevent.js, eventservice.js); camelCase for values, PascalCase for constructors.
  • User input is escaped with escapeHtml before it reaches the DOM.
  • Design tokens live in @theme in css/input.css; components consume them through Tailwind utilities.
  • Internal links and assets are root-absolute so pages work identically from any URL depth.

Deploy Deployment

The app deploys to Firebase Hosting. firebase.json enables cleanUrls with trailingSlash: false, and the folder-per-page layout means each route resolves to its index.html at a canonical, extensionless URL.

npm run build:css                                    # ensure css/output.css is current
firebase deploy --only hosting                       # ship the static site
firebase deploy --only firestore:rules,firestore:indexes   # ship rules + indexes

firebase deploy with no flags does all three at once. The README.md, package.json, css/input.css, and firebase/** paths are excluded from the Hosting upload via the ignore list in firebase.json.


Developer Developer

Built and maintained by Antech — Antony Mwendwa.

Platform Handle
GitHub GitHub Antech-greyhat
Telegram Telegram AntechDevSecOps
X (Twitter) X (Twitter) Antech1629
LinkedIn LinkedIn Antony Mwendwa
WhatsApp WhatsApp +254 714 452 396

If AntechEvents is useful to you, consider a ⭐ and a follow at github.com/Antech-greyhat.


License License

Private. All rights reserved.

About

AntechEvents is a mobile-first personal event management platform for organizing events, calendars, registration links, notes, reminders, scheduling conflicts, and availability in one place. Built with HTML, Tailwind CSS, Vanilla JavaScript, Firebase Authentication, and Firestore.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages