Skip to content

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PlanEOS

An operating system for a small company: EOS-style goal tracking, CRM, chat, live meetings and time tracking — in one bilingual app with no build step.

English · Español

CI vanilla supabase build


What it does

Module What it covers
EOS Rocks, to-dos, scorecard, VTO, headlines
CRM Companies, contacts, pipelines, deals, activities
Chat Slack-style channels and DMs, realtime
Meetings Live agenda, shared notes, attendees
Time Toggl-style projects and time entries
Boards Kanban, scoped per organisation or team

Bilingual (Spanish/English) throughout, light and dark themes, responsive.

Screenshots

Dashboard

The daily view. Your rocks with progress, your to-dos, and the scorecard — the three things an EOS meeting actually runs on.

Scorecard Rocks
Scorecard. Weekly KPIs against a goal, green when met and red when missed. Rocks. Quarterly objectives with owner, status and progress.
Boards Chat
Boards. Kanban scoped per organisation or team. Chat. Channels and DMs over Supabase realtime.
To-dos Time
To-dos. Team and private, with due dates. Time tracking. Timer per project, reportable.

Marketing site

Hero Pricing

Screenshots come from a demo organisation seeded with invented data.

Architecture

No framework and no build step. ES modules served directly, a Supabase project behind them. You clone it, point it at a database, and open the folder.

site/                marketing site
app/
  config/env.js      Supabase URL + publishable key
  js/core/           supabaseClient, auth, orgContext, api, realtime, i18n
  js/components/     appShell, sidebar, modal, kanban, taskDrawer
  js/pages/          one controller per module
  js/i18n/           es.json, en.json
  pages/             one HTML file per module
supabase/
  migrations/        0001_core → 0100_rls
  full_schema.sql    everything in one file
  seed.sql           optional demo data

Why no framework

The app is a set of largely independent screens over a REST/realtime API. A build step would add a toolchain, a lockfile and a deploy artefact without changing what any screen does. Native ES modules cover the actual need: real imports, real code splitting by page, and a file you can edit and reload.

The trade-off is real — no JSX, no reactive rendering, and DOM updates are written by hand in js/core/dom.js. For an app of this size that was a worthwhile trade; for a larger one it would not be.

Security model

Every table has Row Level Security enabled — 34 of 34. Authorisation lives in Postgres policies, not in the client.

create policy crm_contacts_sel on public.crm_contacts
  for select using (public.is_org_member(org_id));

create policy crm_contacts_wr on public.crm_contacts
  for all using (public.is_org_member(org_id))
      with check (public.is_org_member(org_id));

This is why the Supabase key in env.js is publishable and safe to ship to the browser: it identifies the project, it doesn't grant access. Access is decided per row, per request, by is_org_member(org_id).

is_org_member is a security definer helper so that membership lookups don't re-enter the policies that call them — without that, org-membership checks recurse.

Verify tenant isolation yourself

Create two organisations with two different users, then confirm user A cannot see organisation B's data through the API, not just through the UI:

curl "$SUPABASE_URL/rest/v1/crm_contacts?select=*" \
  -H "apikey: $KEY" -H "Authorization: Bearer $USER_A_JWT"

Only org A's rows should come back. If a table ever returns everything, its policy is missing — that's the check that matters.

Setup

git clone https://github.com/alancorrals95/planeos.git
cd planeos

cp app/config/env.example.js app/config/env.js
$EDITOR app/config/env.js          # your Supabase URL + publishable key

Then, in the Supabase SQL editor, run supabase/full_schema.sql (or the migrations in order). Full walkthrough in SETUP.md and supabase/README.md.

Serve the folder with any static server:

python3 -m http.server 8888
# app  → http://localhost:8888/app/
# site → http://localhost:8888/site/

For development, turn Confirm email off under Authentication → Providers, and add your local URL to Authentication → URL Configuration → Redirect URLs.

Status

Functionally complete across all modules listed above. Billing (Stripe) is the remaining piece, and there is no UI yet for creating teams beyond the leadership team created automatically at signup.

License

MIT — see LICENSE.

About

An operating system for a small company: EOS goals, CRM, chat, live meetings and time tracking. Vanilla JS + Supabase, no build step.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages