feat: rename app to Keynctr

This commit is contained in:
Avi 2026-08-31 13:13:47 -05:00
commit a3b509cb09
10 changed files with 38 additions and 20 deletions

View file

@ -1,29 +1,40 @@
# Checkpoint — Impeccable themes + ProfileEditModal (2026-08-27)
# Checkpoint — Keynctr branding and Linux installers (2026-08-31)
## Where things are
- Project: `/home/avi/Projects/Nostr_Keynctr`
- Git repo: `master` @ `8366af7` ("feat: add Impeccable themes (light + dark) + unified ProfileEditModal"). Before it: `832e114` (checkpoint: fix delete/undo), `9e635e7` (fix delete/undo bar), `56c2a6d` (click profile row), `8130c3e` etc.
- Working tree: clean except `.opencode/` (impeccable skill install, not tracked) and `KeynectrAppIconPossibility02.jpeg` untracked (long-standing).
- Git repo: `master` @ `76deca6` ("feat: add Cosmic theme + motion system").
- Working tree: uncommitted Keynctr branding, packaging metadata, and Cosmic palette/branding updates, plus untracked `.directory`, `.opencode/`, `COSMIC_THEME.md`, and `KeynectrAppIconPossibility02.jpeg`.
## What was completed
1. **Fixed broken profile delete/undo** (previous). `src/ipc.rs` missing `DeleteProfile`/`UndoDelete`; added handlers returning `state_view`; exposed `profiles::delete_profile` outside tests; `api.ts`/`AppProvider` now `call<AppState>` via `applyState`; `fakeBackend` delete/undo.
1. **Cosmic branding update.** The Cosmic theme now uses Gold `#F3B407` and Light Blue `#87E6FB`; Cosmic’s dark sidebar presents the logo in white while retaining black-on-white artwork elsewhere. The visible brand is `SOLARPUNK SUMMIT` with `KITCHEN 484`.
2. **Fixed broken profile delete/undo** (previous). `src/ipc.rs` missing `DeleteProfile`/`UndoDelete`; added handlers returning `state_view`; exposed `profiles::delete_profile` outside tests; `api.ts`/`AppProvider` now `call<AppState>` via `applyState`; `fakeBackend` delete/undo.
2. **Themed auto-dismiss undo bar.** Replaced permanent white bar with `var(--primary-soft)` + `var(--primary)` link `Undo and restore profile`, 5s `useEffect` watching `lastDeleted`, shown in both empty/populated states.
3. **Impeccable themes (light + dark).** `src/settings.rs`: `Theme::Impeccable` + `ImpeccableDark` (serde `impeccable-dark`); `types.ts` union extended; `styles.css` added `:root[data-theme='impeccable']` (oklch 97% lacquer light, kinpaku gold `oklch(77% .13 82)`, Alumni Sans 300) and `impeccable-dark` (oklch 15% lacquer-deep, champagne text), editorial refinements (uppercase labels, 8/3px radii, nav left-border active, card offset bar); `SettingsScreen.tsx` adds both options with live `var(--*)` swatches.
4. **Unified ProfileEditModal.** `frontend/src/components/ProfileEditModal.tsx` — Paper Lift modal (`var(--surface)`/`var(--border)`/`16px`/`0 12px 40px`), 3 tabs (Name/Picture/NIP-05) sharing `renameProfile`/`setProfilePicture`/`setNip05`; `ProfilesScreen.tsx` wires `Edit profile` (secondary) alongside legacy ghosts; `DESIGN.md` + `PRODUCT.md` + `.impeccable/design.json` from `impeccable document` (Vault & Atelier, warm ivory/charcoal/coral, 9 primitives).
5. **Linux installers.** Electron Builder now produces both AppImage and Debian targets. Generated artifacts are `frontend/release/SOLARPUNK SUMMIT-0.1.0.AppImage` and `frontend/release/keynectr_0.1.0_amd64.deb`.
6. **Keynctr branding.** Replaced the visible `SOLARPUNK SUMMIT` / `KITCHEN 484` labels with `Keynctr` in the window, page title, sidebar, home screen, settings, and tests. Rebuilt artifacts: `frontend/release/Keynctr-0.1.0.AppImage` and `frontend/release/keynectr_0.1.0_amd64.deb`.
## Commits added in this session (newest first)
- No commit added; packaging metadata and checkpoint updates remain uncommitted.
- `76deca6` feat: add Cosmic theme + motion system (palette/branding refinements currently uncommitted)
- `8366af7` feat: add Impeccable themes (light + dark) + unified ProfileEditModal
- `832e114` checkpoint: fix delete/undo + themed auto-dismiss bar
- `9e635e7` fix: restore profile delete/undo and themed auto-dismiss undo bar
## Verification commands run (all green)
- Rust (repo root): `cargo fmt --check` clean; `cargo clippy --all-targets` 2 pre-existing warnings; `cargo test` 115 passed; `cargo build --release` success
- Frontend (`frontend/`): `npm test` 15 files / 99 tests passed; `npm run typecheck` clean; `npm run lint` clean; `npm run format:check` clean (after `npm run format`); `npm run build` success; `npm run electron:build` success
## Verification commands run
- Rust: `cargo fmt --check`, `cargo clippy --all-targets`, `cargo test` (115 passed), and `cargo build --release` passed; existing warnings remain in `src/ipc.rs` and `src/profiles.rs`.
- Frontend: `npm test` (15 files / 99 tests), `npm run typecheck`, `npm run lint`, `npm run format:check`, `npm run build`, and `npm run electron:build` passed.
- Packaging: `npx electron-builder --linux AppImage deb` passed; AppImage and Debian files verified with `file`.
- Branding verification: `npm test`, `npm run typecheck`, `npm run lint`, `npm run format:check`, `npm run electron:build`, `npm run build`, and `npx electron-builder --linux AppImage deb` passed.
- Frontend build no longer reports the Cosmic font `@import` ordering warning; standard Vite/ESM and ESLint module warnings remain.
- Wayland `--ozone-platform` / `has no handler` messages on `electron:build` are harmless.
## How to resume / reproduce
GUI (Impeccable): `cargo build --release && cd frontend && npm run build && npm run electron:build && npm start` (or dev: `npm run dev` in one terminal + `NOSTR_GUI_DEV_URL=http://localhost:5173 npm start` in second). Settings → Appearance → `Impeccable — Light` / `Impeccable — Dark` (gold on ivory lacquer vs lacquer-deep). Profiles → Delete → see themed undo bar 5s; Edit profile → tabbed modal. CLI: `cargo run -- settings set theme impeccable` / `impeccable-dark`.
GUI (Cosmic): `cargo build --release && cd frontend && npm run build && npm run electron:build && npm start` (or dev: `npm run dev` in one terminal + `NOSTR_GUI_DEV_URL=http://localhost:5173 npm start` in second). Settings → Appearance → `Cosmic — Stardust`. CLI: `cargo run -- settings set theme cosmic`.
- Build installers: `cd frontend && npm run build && npm run electron:build && npx electron-builder --linux AppImage deb`. Install the `.deb` with `sudo apt install ./release/keynectr_0.1.0_amd64.deb`, or run the AppImage with `./release/SOLARPUNK\ SUMMIT-0.1.0.AppImage`.
- Current installers: `sudo apt install ./release/keynectr_0.1.0_amd64.deb`, or `./release/Keynctr-0.1.0.AppImage`.
## Outstanding / next-step items
- Undo restores with empty `secret_key` (stores `ProfileSummary`); needs `StoredProfile` in `undo_history` for full secret recovery.
- `.opencode/` skill files and `KeynectrAppIconPossibility02.jpeg` remain untracked; not part of theme commits.
- `.opencode/`, `COSMIC_THEME.md`, and `KeynectrAppIconPossibility02.jpeg` remain untracked; no commit was created in this session.
- Installer artifacts are local build outputs under `frontend/release/` and are not committed.

View file

@ -511,7 +511,7 @@ function createWindow(): void {
height: 760,
minWidth: 920,
minHeight: 640,
title: 'Keynectr',
title: 'Keynctr',
icon: resolveWindowIcon(),
backgroundColor: '#f6f4f0',
autoHideMenuBar: true,

View file

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Keynectr</title>
<title>Keynctr</title>
</head>
<body>
<div id="root"></div>

View file

@ -1,8 +1,13 @@
{
"name": "keynectr",
"productName": "Keynectr",
"productName": "Keynctr",
"version": "0.1.0",
"description": "A friendly Linux desktop app for managing Nostr profiles and publishing text notes.",
"author": {
"name": "Keynectr",
"email": "maintainers@keynectr.local"
},
"homepage": "https://github.com/avi/Keynctr",
"private": true,
"main": "dist-electron/main.js",
"scripts": {
@ -64,7 +69,8 @@
],
"linux": {
"target": [
"dir"
"AppImage",
"deb"
],
"icon": "build/icon.png",
"category": "Network",

View file

@ -32,7 +32,7 @@ export function Sidebar({ screen, onNavigate }: SidebarProps) {
<img src={logoUrl} alt="" draggable={false} />
</span>
<div>
<strong>Keynectr</strong>
<strong>Keynctr</strong>
</div>
</div>

View file

@ -37,7 +37,7 @@ export function HomeScreen({ onNavigate, onCreateProfile }: HomeScreenProps) {
<div className="screen-inner">
<EmptyState
icon={<Icon name="users" size={30} />}
title="Welcome to Keynectr"
title="Welcome to Keynctr"
description={
<span>
You haven't created a profile yet. A Nostr profile is your identity on the public

View file

@ -187,7 +187,8 @@ export function SettingsScreen() {
</div>
<p className="hint">
"Light" and "Dark" follow your manual selection. "Aurora", "Neon", "Impeccable",
"Impeccable Dark", and "Cosmic" are aesthetic themes with distinctive color palettes.
"Impeccable Dark", and "Cosmic" are aesthetic themes with distinctive color
palettes.
</p>
</div>
</div>
@ -404,7 +405,7 @@ export function SettingsScreen() {
<dl className="info-list">
<div>
<dt>Application</dt>
<dd>Keynectr v{state?.version ?? '?'}</dd>
<dd>Keynctr v{state?.version ?? '?'}</dd>
</div>
<div>
<dt>Backend</dt>

View file

@ -15,7 +15,7 @@ describe('App', () => {
const { user } = renderApp(backend);
render(<App />);
expect(await screen.findByText('Welcome to Keynectr')).toBeInTheDocument();
expect(await screen.findByText('Welcome to Keynctr')).toBeInTheDocument();
expect(screen.getByRole('button', { name: /Create your first profile/i })).toBeInTheDocument();
expect(screen.getByText(/A Nostr profile is your identity/i)).toBeInTheDocument();

View file

@ -48,7 +48,7 @@ describe('HomeScreen', () => {
const { onCreateProfile } = renderHome(backend);
renderWithApp(<HomeScreen onNavigate={vi.fn()} onCreateProfile={onCreateProfile} />);
expect(await screen.findByText('Welcome to Keynectr')).toBeInTheDocument();
expect(await screen.findByText('Welcome to Keynctr')).toBeInTheDocument();
await userEvent
.setup()
.click(screen.getByRole('button', { name: /Create your first profile/i }));

View file

@ -74,7 +74,7 @@ describe('SettingsScreen', () => {
installFakeBackend(backend);
renderWithApp(<SettingsScreen />);
expect(await screen.findByText(/Keynectr v/)).toBeInTheDocument();
expect(await screen.findByText(/Keynctr v/)).toBeInTheDocument();
expect(screen.getByText('Rust (nostr-sdk)')).toBeInTheDocument();
});