Page templates (views/website_pages.xml): - Footer social icons pointed at facebook.com/youtube.com/instagram.com homepages; now TNCSC's own profiles. - "View Event" pointed at a static product mock-up; now /event. - Home "Book Now", Events "Register Event" and the picnic page's "Add To Cart" (which went to /contact) now open the real Summer Picnic registration, falling back to /event if that event is missing. - Home All/Event tabs were href="#"; now /event. - About "Learn More" went to the contact form; relabelled "Contact Us". - Benefits "Become A Member" now goes to /membership/registration. Stock Odoo chrome on built-in pages (login, event/school registration): - Footer replaced with a TNCSC footer (real links, company email, only configured social profiles) instead of demo content with info@yourcompany.example.com, a 555 number and dead "#" links. Priority 90 so it also wins over the website-specific footer copy on the server. - Header "Contact Us" now goes to /contact; the demo phone number is replaced by the company email. community_portal: /my and /my/home (the "Member Login" target) returned a 500 for anonymous visitors because of this Odoo build's auth='user' redirect bug; they now redirect to the login page. website_pages.xml is noupdate, so upgrades never applied template fixes. The 19.0.1.2.0 pre-migrate reloads it once in init mode (this overwrites website-editor edits to those pages; none exist on the server). Verified locally: upgrade of tncsc_site succeeds, every internal link on 16 pages resolves (200/30x), and a fresh install passes 34/34 tests for community_membership, community_portal and tncsc_deployment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Community OS
A brand-neutral, resellable suite of Odoo 19 Community modules for community and cultural organizations. First deployment: the Tamil Nadu Cultural Society of Canada (TNCSC).
Vendor: Metatroncube Software Solutions LLP · Waterloo, Ontario Target platform: Odoo 19 Community Edition (LGPL-3) · PostgreSQL 16 · Python 3.12
community_*is a placeholder module prefix. Replace it with a unique vendor prefix before publishing to the Odoo App Store so technical names never collide with anything already listed.
Layered architecture
┌─────────────────────────────────────────────────────────────┐
│ DEPLOYMENT LAYER (per client — data only, no logic) │
│ tncsc_deployment: branding, tiers & prices, chart of │
│ accounts, email copy, website pages, user groups │
└───────────────▲─────────────────────────────────────────────┘
│ depends on
┌───────────────┴─────────────────────────────────────────────┐
│ PRODUCT LAYER (brand-neutral, resellable, LGPL-3) │
│ community_membership event_qr_ticketing community_school │
│ community_classifieds community_benefits community_interac│
│ community_theme_base community_portal │
└───────────────▲─────────────────────────────────────────────┘
│ depends only on
┌───────────────┴─────────────────────────────────────────────┐
│ ODOO 19 COMMUNITY CORE (never Enterprise) │
└─────────────────────────────────────────────────────────────┘
Product-layer modules never mention a client name, never hardcode a price,
a colour, an account code, or an email address. Anything client-specific
is a configuration record, seeded only by a *_deployment module. Landing
a new client means writing a new clientname_deployment module — the
product code never changes.
Modules
Product layer (brand-neutral, sellable)
| Module | Purpose |
|---|---|
community_theme_base |
Configurable brand tokens (colours, logo, fonts) via settings |
community_membership |
Member profiles, tiers, family grouping, renewals, QR membership card |
event_qr_ticketing |
QR ticket per event registration, staff check-in / verification |
community_school |
Programs, classes, enrollment, attendance, LMS link, parent portal |
community_classifieds |
Member-gated classifieds board with moderation and auto-expiry |
community_benefits |
Benefit centres and per-tier member benefit entitlements |
community_interac |
Interac e-Transfer semi-automated payment provider (Canada) |
community_portal |
Unified member portal dashboard, soft-detects installed modules |
Deployment layer (per client — data only)
| Module | Purpose |
|---|---|
tncsc_deployment |
TNCSC branding, tiers/prices, chart of accounts, email copy, website pages, user groups |
Independent vs. bundled
Every product module installs standalone on a stock Odoo 19 CE with only
its declared Community-core dependencies — none require another
community_* module to function, with one deliberate exception:
community_benefits hard-depends on community_membership (a benefit is
entitled per membership tier, so the dependency is intrinsic to what it
does). community_school and community_classifieds soft-detect
event_qr_ticketing/community_membership when present and degrade
gracefully without them. community_portal soft-detects all of the above
and only renders cards for whichever are installed. This means each module
can be sold and installed on its own, or bundled as the full suite.
Local development
cd deploy
docker compose up
Odoo will be available at http://localhost:8069. The ../addons folder is
mounted read-write, so changes to module code are picked up on restart (dev
mode reload is enabled in deploy/odoo.conf).
Licensing & resellability guardrails
- Every product module is licensed
LGPL-3. - No
community_*module may depend on an Odoo Enterprise module — seeAppendix Ain the project plan for the Community-only allowlist. - No client identity (name, email, colour, price, account code) may appear
in a product module. This is enforced in CI by
scripts/check_brand_leak.py. - All client-variable behaviour is configuration data, seeded by the deployment layer, never a literal in product code.
- Every product module ships an App-Store-ready manifest, a
tests/package, and astatic/description/index.htmllisting page.
See CommunityOS_Implementation_Plan_for_Claude_Code.md for the full,
phase-by-phase build plan, and HANDOFF.md for exactly where the build
currently stands, how to resume it, and known gotchas.
CI
.github/workflows/ci.yml installs every module against Odoo 19 +
Postgres 16 with --test-enable, runs the brand-leak grep, and lints with
flake8 / pylint-odoo.