Matrix-based chat client with Spaces, Categories, and Rooms.
Status: Alpha (v0.1.0). Priorities follow GitHub Issues for this repo.
- Framework: Nuxt 4, Vue 3
- Matrix: matrix-js-sdk
- UI: Nuxt UI, Tailwind CSS (Dark Mode default)
- Tests: Vitest (Unit/Integration), Cucumber + Playwright (E2E)
- Node.js 20+
- Matrix account (e.g. matrix.org)
npm installnpm run devOpen http://localhost:3000.
By default, Decentra logs debug traces only to the browser console. You can optionally forward those traces to a remote ingest endpoint by setting environment variables (recommended via a local untracked file):
cp .env.example .env.localThen set one or more of:
NUXT_PUBLIC_DEBUG_LOG_INGEST_URL(enables remote logging)NUXT_PUBLIC_DEBUG_LOG_SESSION_ID(optional)NUXT_PUBLIC_DEBUG_LOG_SESSION_HEADER(optional, e.g.X-Debug-Session-Id)
npm run build
npm run preview# Unit tests
npm run test:unit
# Integration tests
npm run test:integration
# E2E tests (builds app, starts server, runs Cucumber)
npm run test:e2e
# E2E smoke tests only (@smoke-tagged scenarios)
npm run test:e2e:smoke
# E2E with visible browser
npm run test:e2e:headed
# Coverage (currently from unit Vitest config)
npm run test:coverage
# CI fast lane (unit + integration + e2e smoke)
npm run test:ci:fast
# CI full lane (unit + integration + coverage + full e2e)
npm run test:ci:full
# Install Playwright browser (one-time)
npm run prepare:e2eFor credential-based E2E scenarios, create a local env file:
cp tests/e2e/.env.e2e.example tests/e2e/.env.e2e.localThen fill E2E_MATRIX_USERNAME and E2E_MATRIX_PASSWORD.
The local file stays untracked.
This repo uses .github/workflows/ci.yml with two lanes:
- Fast lane: runs on push + pull request (
test:ci:fast). - Full lane: runs nightly and optionally manual
(
test:ci:full).
Set these in GitHub under Settings > Secrets and variables > Actions:
E2E_MATRIX_HOMESERVER(optional, defaults tohttps://matrix.org)E2E_MATRIX_USERNAMEE2E_MATRIX_PASSWORD
- Open your repository on GitHub.
- Go to Actions.
- Select workflow CI.
- Click Run workflow.
- Set
run_fulltotrueif you want the full lane.
@nuxt/test-utils is intentionally not part of the current test runtime.
In our current dependency set, it caused peer dependency conflicts in CI while
its Nuxt runtime helpers were not actively used by our tests.
We can reintroduce it later when we add dedicated Nuxt runtime integration
tests (setupTest(), plugin/runtime integration, Nitro route tests).
app/
├── composables/useMatrixClient.ts # Login, crypto, sync, messaging
├── composables/matrix/matrixRegistrationUia.ts
│ # Email signup UIA loop
├── pages/
│ ├── login.vue / signup.vue
│ ├── signup/verify-email.vue
│ ├── chat.vue
│ └── index.vue
└── components/Chat/
├── RoomList.vue
├── MessageList.vue
└── MessageInput.vue
Signup uses Matrix User-Interactive Authentication against
/register: first request may return 401 with session, flows,
and params; the client keeps the session and completes stages in order.
Delegated auth (MAS / OAuth — e.g. matrix.org)
If /.well-known/matrix/client includes org.matrix.msc2965.authentication,
the homeserver typically blocks legacy POST /register for web clients but
delegates new-account creation (and related flows) to a Matrix Authentication
Service (OAuth/OIDC).
- Set
NUXT_PUBLIC_SITE_URLto your app's publichttps://origin without path (Matrix dynamic client registration rejectshttp://localhostredirects; use an HTTPS tunnel / preview URL for local OAuth). - Optional
NUXT_PUBLIC_MATRIX_OIDC_CLIENT_ID— static OAuth client id if you register one yourself. - Redirect/callback
/auth/matrix-oidc/callbackcompletes the PKCE exchange, restores the Matrix JS SDK session (matrixOidcNative.ts,useMatrixClient).
Supported stages today (legacy /register UIA)
| Stage | Notes |
|---|---|
m.login.email.identity |
Email verification link; continuation on /signup/verify-email |
m.login.recaptcha |
reCAPTCHA v2/v3 from homeserver params |
m.login.registration_token |
Opaque token; unstable ids ending in .login.registration_token treated the same |
m.login.terms |
Policy links from params; user accepts before continuing |
m.login.dummy |
Included in finalize loop when required by the server |
Explicit non-support
m.login.ssoas an in-flow stage after/registeralready returned UIA (session+ flows) — not wired in-app; where MSC2965 is advertised, prefer the delegated OAuth button on the sign-up page instead.m.login.msisdn– Phone/SMS registration is not implemented; users get a clear “not supported” message instead of failing silently.
When several flows include email verification, Decentra picks a shortest flow whose stages are all supported.
Locations: matrixRegistrationUia.ts (logic), signup.vue /
signup/verify-email.vue + SignupTermsStep.vue (UI).
Regression tests: npm run test:unit (see tests/unit/composables/matrixRegistrationUia.spec.ts
and signup page specs).
This project is licensed under the GNU Affero General Public License v3.0
or later (AGPL-3.0-or-later). See LICENSE for details.