Arkive

Architectural Overview

Sidekick's architectural overview — an API-first platform tuned for solo developers

As of
Version2.2.1
Kinddocument, for software engineers
Length4,821 words, about 21 min
Tagssidekickprojecttechnicalarchitecture

1. Executive summary

Sidekick will be a modular, API-first Personal Operating System designed with multiple types of clients in mind: a Next.js-powered web app, a Progressive Web Application (PWA), and above all, a programmable API platform for agents, automations, workflows, and CLI tooling. The product vision and its modules are defined in the high-level PRD, Project Sidekick — A Bird's Eye View; section 5 of this document maps that vision onto the technical architecture.

The application architecture intentionally prioritizes security through enforceable structures, maintainability for a solo developer, incremental scalability, future support for offline capabilities, and API parity across browsers, CLIs, and agents. The system is NOT designed as a hyper-scale enterprise platform from day one. Instead, it is designed to evolve safely without requiring major architectural rewrites.


2. Architectural philosophy

2.1 API-first platform

Sidekick will be an API-first product, exposed publicly through detailed documentation to let power users extend and customize its features. To keep things simple and avoid architectural drift, we will not build private APIs for our internal clients. Even our native clients (web app, CLI, agents, native apps, and automations) must route through the same public APIs to access features.

This strategy provides several benefits:

  1. The product’s business logic is centralized within the API layer.
  2. In the future, it will be easier to integrate capabilities with third-party providers.
  3. All features are inherently CLI and AI-agent compatible.
  4. Authorization is centralized.

The MVP intentionally excludes API versioning to keep the scope manageable and simple, while keeping the architecture flexible enough to shift toward that goal when warranted.

2.2 Enforced conventions, especially security

We want to implement every possible guardrail to enforce architectural guidelines and standards through linting and testing. This strategy eliminates the cognitive load of having to remember every rule. This is prominently reflected in our security enforcement:

  1. Route security and its context are centralized.
  2. Feature entitlement checks are centralized.
  3. API-scope checks are centralized.

2.3 Modular but pragmatic

Sidekick’s architecture is intentionally designed to balance complexity and simplicity in a way that works efficiently for a solo developer today, while remaining open enough to introduce necessary complexity later. For example, whether a specific feature is authorized or not, the MVP will build all features, deploy everything, and share the same runtime (i.e., features are not containerized).

This avoids premature complexity and supports a rapid development cycle. The architecture remains open enough to support runtime feature loading, microservices, independent deployments, and offline sync engines without large-scale rewrites.

2.4 Built for one, designed for many

The MVP serves an audience of one, but Sidekick is intended to grow into a real product. This principle governs every design choice:

  1. Never bake single-user assumptions into schemas or services. Every user-data table is keyed by userId under RLS — multi-tenancy is already real, not aspirational.
  2. Feature entitlements, invites, and billing remain in the plan — sequenced late, but never removed.
  3. Quotas, limits, and usage tracking are designed as per-user concerns from the start.
  4. Prefer reversible choices: a Postgres-based graph pattern now that can become a dedicated graph database at scale; a static model router now that can become a routing gateway at scale.

3. System overview

architectural-overview


4. Monorepo structure

4.1 Dependency rules

  • NEVER import apps/* into packages/*: Violating this rule introduces circular dependencies, invalid build graphs, hidden coupling, and future deployment problems.
  • packages/features-registry serves as the ledger of all features Sidekick will offer. It will host feature manifests, metadata, and registration information.
  • packages/core must ALWAYS remain feature-agnostic.

Layers are enforced by folder and by pnpm lint: apps, the registry, features (packages/features/*), platform (packages/platform/*) and foundation (packages/foundation/*), each importing only layers below it. The full rules are in Dependency flow.


5. Product context — the module system

Sidekick's features are named product modules, defined in the high-level PRD (Bird's Eye View). Module names are the canonical vocabulary everywhere: feature slugs, package names, entitlements, and plan phases all use them. Detailed per-module PRDs live under Docs → Product requirements and are written before each module's implementation begins.

5.1 Module → package mapping

Module Purpose Package MVP
Taxila Knowledge management: atomic notes + knowledge sources (live links, captured content, markdown), metadata enrichment, RAG substrate packages/features/taxila Yes
Zinsser Writing app + AI writing coach trained on the user's own style packages/features/zinsser Yes (editor first; coach after AI layer)
Core Drive The value system: principles, mental models, priorities, plans — context layer for all AI features packages/features/core-drive Yes
Alter Ego AI confidant grounded in Core Drive + Taxila packages/features/alter-ego Yes
War Room Planning and strategy (tasks, day planning) packages/features/war-room Yes
Factory Execution and automation. MVP scope: push-button workflows + configurable input defaults packages/features/factory Partial
Parrot Voice dictation with gesture support — No (post-MVP)

Bookmarks are not a standalone feature: a bookmark is a Taxila knowledge source of type link. Recipes and Budget are backlogged as future "minions".

5.2 Core Drive & context assembly

Core Drive is not a feature that only Alter Ego talks to — it is baked into the entire system. How War Room plans, how Factory executes, how automations run: all of it is conditioned by Core Drive. It starts as a handful of principles but will grow into thousands of entries across categories:

Category Nature Loading behavior
Identity Who the user is, brief history Kernel (always loaded)
Principles Universal truths ("No do-overs") — apply almost everywhere Kernel (always loaded)
Communication styles How the user prefers to communicate and write Kernel (always loaded)
Mental models Situational algorithms ("never shop hungry" → spending tasks only) By applicability metadata
Heuristics Mental shortcuts for low-consequence situations By applicability metadata
Tools & systems The user's day-to-day toolchain By applicability metadata
Preferences & constraints Standing preferences and hard limits By applicability metadata
Domain knowledge Subject-matter knowledge Lives in Taxila, not Core Drive — Core Drive entries link to it via the graph service

Because Core Drive powers every AI-touched operation, it must be context-size efficient. That drives the design below.

5.2.1 Tiered context model

Context for any AI-touched operation is assembled from three tiers:

  • Tier 0 — the kernel. Identity, universal principles, communication style. Always injected, under a hard token budget (~1–2K tokens). The budget creates deliberate curation pressure: an entry earns kernel status and is demoted when it stops being universal.
  • Tier 1 — conditionally loaded Core Drive. Mental models, heuristics, tools, preferences — retrieved primarily by applicability metadata (domain, situation, task type — implemented as global tags from 5.3, e.g. #domain:spending, #situation:planning), with vector similarity as a secondary net. Applicability tags are the primary key precisely because "never shop hungry" must load when the task is about spending, not when the prompt happens to resemble it.
  • Tier 2 — situational state. Current projects, roles, prioritized backlog, goals, calendar, daily brief — owned by War Room and Factory. Assembled via ordinary structured repository queries (not embeddings).

Hard boundary rule: Core Drive never stores state; War Room and Factory never store values. Core Drive is timeless; Tier 2 is operational and current.

5.2.2 Entry anatomy

Each Core Drive entry stores, from day one:

  • category — drives tier rules (identity | principle | mental-model | heuristic | tool | preference | …)
  • directive — a compact one-line imperative form used for injection ("Never restart a project from scratch; pause and resume"), alongside the full prose the user reads. This is the primary context-size lever: thousands of entries stay affordable because the distilled form is what gets injected.
  • weight — priority for conflict resolution when two loaded entries clash in a situation
  • kernel — boolean marking Tier 0 membership
  • Applicability via global tags (5.3); usage tracking (e.g. lastLoadedAt) so dead-weight entries become visible for curation

5.2.3 The Context Assembler

A single Context Assembler service in packages/core/ai (alongside the model router, 5.5) is the only way features obtain AI context. Input: a task descriptor (feature, taskType, effortLevel). Output: an assembled context bundle (kernel + applicable Tier 1 entries + relevant Tier 2 state, within budget). No feature ever hand-rolls its own context gathering — the same enforced-convention philosophy as withApiGuard: one choke point, impossible to drift.

Effort Level is a first-class parameter in the AI request contract. It is a budget knob on the assembler — how many tiers are consulted, retrieval depth (k), how much situational state — and the model router responds to it too (higher effort can route to a more capable model). One parameter; two systems respond.

MVP cut: the schema fields above and a v1 assembler (kernel + top-k by tag/similarity) ship with the first AI feature; effortLevel exists in the contract from day one but initially only tunes retrieval depth. Tier 2 assembly arrives when War Room/Factory exist. The interface is the investment; the sophistication arrives later.

5.2.4 Relationship to Taxila

  • Taxila is a large, growing corpus consumed via top-k similarity retrieval.
  • Core Drive is curated and assembled by tier — kernel entries are injected wholesale, never gambled on a vector-similarity match.
  • Core Drive follows a reflective write pattern: when reality forces a deviation from a principle, the deviation becomes a data point that refines the value system.

5.3 Graph store & global metadata service

New possibilities emerge when features combine ("power of synergies" in the PRD). While each feature owns its data tables, relationships between entities and global metadata live in a shared service — built in the MVP so Taxila uses it from day one.

This is a graph pattern, not a graph database. At MVP scale, plain PostgreSQL tables with recursive CTEs for traversal are sufficient. All access goes through Synergy's own repository in packages/platform/synergy — the swap boundary if scale ever demands a dedicated graph engine.

Design constraints:

  1. All feature entities use client-generated UUIDs (existing invariant) and register a linkable entity type with Synergy — the registry assembles those registrations.
  2. Synergy's tables and migrations (relationships, entity index, version log) live in packages/platform/synergy, not in packages/core. Synergy stays feature-agnostic because it stores opaque typed IDs, never feature schemas. See Synergy.
  3. Global tags and tag_applications tables provide metadata across all entity types.
  4. Edges and tags are user data: RLS by userId, syncable (soft-delete + trigger) rules apply.

5.4 Interaction model — command palette first

The MVP UI is a single command box in the center of the page (think Cmd+P in VS Code or / in Notion): type the command to run or the page to open. No site layout, navigation chrome, or logo. Conventional layouts are deferred.

This makes the MVP keyboard-heavy, and undiscoverable to anyone who doesn't know what they're looking for — an accepted tradeoff for an audience of one.

5.5 Provider-agnostic AI layer

Sidekick's AI capabilities must not be coupled to any single LLM provider. A static model router in packages/core/ai maps task types to provider/model via configuration, built on the Vercel AI SDK's unified LanguageModel interface and createProviderRegistry():

  • Features request capabilities (chat, classify, coach) — never concrete models.
  • Switching providers or models is a configuration change, not a code change.
  • The router honors effortLevel from the AI request contract (5.2.3): higher effort may resolve to a more capable model for the same task type.

Designed extension point: dynamic prompt-classifying routing and gateways (Vercel AI Gateway, OpenRouter, LiteLLM, NotDiamond) compose with the AI SDK. Adopting one later replaces only the router's resolution function — features are untouched.

5.6 Source attribution in AI responses

AI responses may blend two source classes: internal knowledge (RAG over Taxila/Core Drive) and live web retrieval. The response contract must carry per-segment source class — enabling color-coded rendering of sentences by origin — plus footnoted citations to sources.

Architectural implication: AI responses are structured streams (segments + sources), not plain text streams. The streaming protocol must be designed with this in mind from the first AI feature, even if web retrieval itself ships later. First consumer: Alter Ego (see its PRD under Docs → Product requirements once written).

5.7 Evolvability — how product changes flow

Requirements will keep evolving as clarity grows. To keep both this document and the plan flexible:

  1. The PRDs are product truth — the high-level PRD plus per-feature PRDs written before each feature starts.
  2. This document describes mechanisms and invariants, not feature lists. Module-level product changes should only ever touch section 5 (this mapping) — never the security, RLS, repository, or offline sections.
  3. Changes flow one way: PRD → section 5 mapping → living plan phases.

6. Technology stack

Layer Choice
Frontend Next.js 16 App Router
Language TypeScript Strict
DB Supabase PostgreSQL
ORM Drizzle ORM
Styling CSS modules and ui on native HTML (Mantine until lesson M1)
Editor Tiptap
AI SDK Vercel AI SDK
LLM Provider-agnostic router (default: Anthropic Claude)
Embeddings OpenAI text-embedding-3-small
Monorepo Turborepo + pnpm
Hosting Vercel (App), Cloudflare Workers (public site)
Native Shell Capacitor

7. Security

All routes must use withApiGuard()—direct route handlers are strictly prohibited.

Every request must pass through authentication, feature entitlement checks, Row-Level Security (RLS) context setup, and API scope validation before the request is honored. Without withApiGuard, routes begin to drift and security flows become inconsistent or even erroneous over time (e.g., a developer might forget to validate an API scope).

This is in line with our philosophy of enforced conventions (section 2.2). We make secure behavior easy to implement and difficult to bypass.


8. Authentication

The web app, PWA, and iOS app will use cookie-based sessions for authentication. The CLI and agents will use bearer keys. API keys will support SHA-256 hashing, specific scopes, expiration dates, revocation, and last-used tracking.

8.1 API key schema

(Schema details pending)


9. Row-Level Security (RLS)

9.1 Canonical pattern

We will use PostgreSQL’s Row-Level Security features to ensure users can only see and operate on records (rows) they are permitted to access. By default, PostgreSQL enforces RLS for ALL non-superuser roles. We will use Drizzle ORM to query the database, and since Drizzle connects to PostgreSQL via a non-superuser role (app_runtime), RLS will be enforced for all Drizzle queries at the system level.

Sidekick will feature two types of tables with distinct RLS policies:

What makes an entity “syncable” or “non-syncable”? A syncable entity must carry three timestamp columns: createdAt, updatedAt, and deletedAt. The presence of updatedAt and deletedAt indicates that the application supports offline features. Using these timestamps, conflict resolution occurs across all clients and the server when they are online. A non-syncable entity doesn’t have these attributes because it doesn't require conflict resolution and relies on hard deletions.

Because non-syncable tables hard-delete rows, we will not include a deletedAt clause in their RLS policy. However, syncable entities will have a deletedAt guard in the USING clause to filter soft-deleted rows from results. Notice that we omit the deletedAt guard in WITH CHECK, as reversing a soft-deleted row is a legitimate operation.

Difference between ENABLE and FORCE RLS:

  • ENABLE ROW LEVEL SECURITY: Turns RLS on for the table. The key exception is that the table owner (and superusers) bypass RLS by default. If no policies exist, the default is deny-all.
  • FORCE ROW LEVEL SECURITY: Makes RLS apply to the table owner as well. It does not affect superusers or roles with the BYPASSRLS attribute. FORCE is only meaningful in combination with ENABLE.

Difference between USING and WITH CHECK: The USING clause is a guard for existing rows (applied to rows already in the table). The WITH CHECK clause guards which row values are allowed to result from a write (applied to the new/proposed row data).

Command USING applies? WITH CHECK applies?
SELECT Yes —
INSERT — Yes
UPDATE Yes (which rows you may update) Yes (what the row may become)
DELETE Yes —
MEANING filters existing rows to prevent unauthorized operations validates proposed changes against policy criteria

9.2 RLS Helper

The application MUST NEVER manually inject RLS context inline. We will always use the RLS helper: withRLS(userId, ...).

Notice the presence of the db.transaction wrapper here, which is a critical security measure. Without this wrapper, set_config with is_local = true will not reset once the query finishes execution. These settings would persist across the entire pooled connection, leaking the current user ID to subsequent requests.

9.3 Soft-delete trigger functions

The Sidekick database will define two shared functions to enforce soft-delete constraints: enforce_soft_delete and block_update_on_deleted. These functions ensure that non-superuser roles cannot hard-delete or update soft-deleted rows. All feature tables will use these shared functions to enforce soft-delete constraints.

9.4 Database security summary

Constraint Mechanism Enforced at
User sees only their own rows RLS USING clause Database
Soft-deleted rows invisible to users RLS USING clause Database
Hard deletes blocked BEFORE DELETE trigger Database
Updates on deleted rows blocked BEFORE UPDATE trigger Database
SELECT filtering (belt) where(isNull(deletedAt)) in repos Application

Triggers fire for all roles including the service role and superuser. RLS is enforced because Drizzle connects as app_runtime (non-superuser). createAdminClient() bypasses RLS but not triggers.

9.4.1 createAdminClient—a Supabase interface

The createAdminClient() executes queries as a superuser role, bypassing RLS entirely. Queries executed this way will return all deleted and non-active-user rows. This is intentional and reserved for setup, configuration, maintenance activities, or specific user flows like profile creation.

9.4.2 Drizzle client

We must not bypass RLS for most regular user-flow queries. This is where we will use the Drizzle client to query via the non-superuser role.

Supabase client Drizzle client
await admin.from('notes').select('*'); db.select().from(table);
Executed as SELECT * FROM notes SELECT * FROM notes WHERE deleted_at IS NULL AND user_id = <userId>
superuser role app_runtime - non-superuser role
No RLS Enforces RLS
Enforces triggers Enforces Triggers

9.4.3 Funnel all reads through DB repository client

By convention, we want to ensure that all queries are executed under the right context. Therefore, every query must be routed through the DB repository layer. Never execute rogue database queries directly. Whether utilizing createAdminClient or Drizzle ORM, funneling queries through the repository ensures the right contextual guards are applied.


10. API guard

We will use the withApiGuard wrapper to centralize authentication, feature entitlements, RLS, and scope validations.

10.1 How withApiGuard will be implemented?

See With API Guard for how the guard is implemented and used.

10.2 How withApiGuard will be used?

See With API Guard for how the guard is implemented and used.


11. Repository architecture

11.1 Query flow

All queries flow strictly from UI -> Repository -> API -> Database. This abstraction is intentional and future-proofs the app for when the flow evolves into UI -> Repository -> Local DB -> Sync Engine -> API -> Database. In this manner, the UI will never care how data flows.

11.2 Server actions

Server Actions are not allowed. Every mutation goes through an API route handler wrapped in withApiGuard, which is how we keep our API-first guarantee. See Server Actions.


12. Offline-ready design

While offline capabilities are excluded from the MVP, the architecture is designed to support easier implementation in the future.

12.1 Constraints

  • UUIDs: Clients will generate UUIDs to prevent collision issues later.
  • Idempotent APIs: Repeated requests with the same ID must produce the same result. This is critical for sync reliability.
  • Repository layer mandatory: The repository layer MUST NOT be bypassed. This is the primary abstraction boundary enabling future sync support.
  • Soft deletes are mandatory: All syncable entities must support soft deletes, and queries must filter soft-deleted records.
  • updatedAt is the source of truth: Every syncable entity includes createdAt, updatedAt, and deletedAt. Conflict resolution depends upon updatedAt.
    • Deleting offline: If a row is deleted locally while offline, deletedAt allows the server to easily resolve whether the row was deleted by the user or simply hasn't synced yet from another client.
    • Hard deletes are irreversible: Soft deletion is preferred to support offline capabilities and allow users to reverse accidental deletions safely.

13. Embedding pipeline

Embedding writes must be asynchronous, atomic, retryable, and observable.

13.1 embeddingStatus field

Every content table that participates in the embedding pipeline MUST include an embeddingStatus field. This field is the source of truth for embedding state, enabling:

  1. Querying for un-embedded or failed content.
  2. Manual or automated retry of failed jobs.
  3. Visibility into pipeline health without log-scraping.
  4. Safe re-embedding after model upgrades.

Status transitions: Any content with embeddingStatus = 'failed' MUST be logged and retryable. Silent failures are strictly unacceptable.

13.2 Atomic writes

Embeddings must be written as a single atomic transaction. Never delete and then insert outside a transaction, as doing so temporarily makes those embeddings unavailable.

13.3 Retry policy

Embedding jobs must retry twice using an exponential backoff strategy, log all failures, and set embeddingStatus = 'failed' after retries are exhausted.

13.4 Observability

At minimum, the pipeline must support structured logs, failed embedding logs, and latency visibility. The MVP does not require full observability infrastructure.


14. Feature system

The MVP will support a feature system with build-time registration, treating isolated packages as features and controlling them via entitlements. Inactive (unauthorized) features are still built, which is an acceptable tradeoff for the MVP. The system is designed this way to support future evolution into runtime plugins, feature-specific deployments, and microservices without major rewrites.


15. Database migration

Package-level migration scoping: Every feature package owns its own schema.ts, drizzle.config.ts, and migration scripts. There is NO global Drizzle config. Migration orchestration: We will use a pnpm db:migrate command in the root monorepo to orchestrate package discovery, run migration scripts in the correct order, and fail fast on errors. This package-level scoping eliminates schema drift, inconsistent environments, and hidden migration dependencies.


16. Background jobs

For the MVP, Sidekick will use lightweight async background execution using waitUntil(), Vercel background execution, and retry wrappers. Later, this will evolve into Inngest, queues, cron workflows, and distributed workers without changing API contracts.


17. Observability

At minimum, the MVP will support request logging, failed job logging, API latency logging, and auth failure logging. Logging will be done inside withApiGuard() for centralized visibility.


18. Developer rules

  1. All API routes must use withApiGuard().
  2. Never set RLS context manually. Use withRLS() only.
  3. Never mutate data outside the API layer.
  4. Never import from apps/* inside packages/*.
  5. The repository layer must not be bypassed.
  6. All syncable APIs should be idempotent.
  7. Never hard-delete syncable entities; all queries against syncable tables must filter where(isNull(table.deletedAt)).
  8. All content tables participating in the embedding pipeline MUST include an embeddingStatus field. Set it to 'failed' after retries are exhausted. Never silently drop failed embedding jobs.
  9. Never use createAdminClient().from(...).delete() to hard-delete rows from syncable tables. The BEFORE DELETE trigger rejects this. Hard-deletes that must bypass the trigger (e.g., GDPR erasure) require a dedicated Drizzle transaction using SET LOCAL to bypass constraints safely.

19. Operational details

19.1 Types of Supabase clients

Client File Key Used In
createBrowserClient() browser.ts publishable key Client Components ('use client')
createServerClient() server.ts publishable key + cookies Server Components, Route Handlers (Node.js runtime)
createProxyClient(req, res) proxy.ts publishable key + request cookies proxy.ts only (Edge runtime)
createAdminClient() admin.ts secret key (bypasses RLS) Server-only, trusted operations

The key insight: publishable key ≠ identity. All non-admin clients use the same publishable key, which doesn't grant data access on its own. Access is unlocked by the logged-in identity carried in the session cookies.

  • Browser client: Runs in the user's browser. It cannot hold the secret key, cannot run Drizzle, and cannot perform mutations that bypass the API layer. It is meant strictly for reads and auth.
  • Server client: Runs on the server during rendering or inside a route handler.
  • Proxy client: Runs at the edge in middleware (proxy.ts). Its job is session refresh and redirecting unauthenticated users before the request reaches the route.

19.2 Middleware responsibilities

proxy.ts is responsible for session refresh, redirecting unauthenticated users, and excluding API routes from redirect behavior. It must not contain authorization logic, which strictly belongs in withApiGuard().

19.3 Mantine setup requirements

Mantine leaves the App in lesson M1, replaced by native ui primitives (D255). These notes apply until then.

To prevent hydration errors with Mantine's theme injection, we must add suppressHydrationWarning to the <html> element. defaultColorScheme="auto" must be set on both ColorSchemeScript and MantineProvider.

19.4 Styling through CSS Modules

All styling in the App and its packages uses CSS modules without exception. The public site (apps/www) is the one exemption (D47 revised). Pure Mantine style props that set visual styles inline are banned and enforced via the no-mantine-style-props ESLint rule. Behavioral props are an acceptable compromise.

19.5 Centralized copy

To ensure consistency across the application, all user-visible strings must live in packages/copy. Never hardcode strings directly in source files. This is superseded by D243: from lesson I1, strings live in catalogs colocated with each package and packages/copy is deleted.

19.6 Runtime patterns

  • useNavigation hook: Always use useNavigation() instead of calling router.push() alone to ensure router.refresh() is called, preventing stale server-rendered UI.
  • Force-dynamic: Add export const dynamic = 'force-dynamic' to the layout of every route group that touches Supabase cookies to prevent static pre-rendering failures.

19.7 Profile creation — Postgres trigger

User profiles are created via a Postgres trigger on auth.users, not via an API route. This ensures reliability across auth providers and prevents race conditions, as profile creation becomes part of the same database transaction.

19.8 Deferred decisions

  • GraphQL + Relay — Deferred to Post-MVP: The MVP will use a REST API. Right now, I am learning a lot as it is with new backend concepts and application architecture. I don’t want to add the burden of configuring GraphQL at this juncture and increase my cognitive load. Additionally, withApiGuard maps cleanly to REST.
  • API Versioning (/api/v1/) — Deferred to Post-MVP: Adding versioning right now adds complexity with no current benefit, as the MVP only has one client and breaking changes can be coordinated directly.

19.9 Tiptap requirements

Embedding generation should operate on semantic markdown output rather than raw text extraction whenever possible.

19.10 AI / RAG requirements

The pipeline requires pgvector, HNSW indexing, semantic chunking, async embedding generation, and streaming AI responses.

19.11 CLI requirements

The CLI is a first-class architectural citizen. It must use the same public API surface as external agents.

19.12 PWA requirements

The architecture requires an installable web app, manifest, service workers, and an offline mobile-compatible shell.

19.13 Capacitor / iOS Strategy

The MVP native strategy remains Capacitor + hosted Next.js application. The architecture intentionally delays embedded offline databases and native sync engines until post-MVP.

19.14 MVP implementation phases

  1. Groundwork ✅
  2. Front Door (auth, DB-level RLS, hardening) ✅
  3. Gatekeeper (withApiGuard, feature system, entitlements, logging) ✅
  4. Synergy (relationships, entity index, tags, version log)
  5. Taxila (+ command-palette shell)
  6. Zinsser (editor)
  7. Alter Ego (Core Drive + AI layer)
  8. War Room (+ Factory push-button workflows)
  9. Pocket (PWA & native shell)
  10. Terminal (API keys & CLI)
  11. Watchtower (observability & hardening)
  12. Open House (dogfooding, optional)
  13. Storefront (billing, optional)

See the living plan for the authoritative task breakdown.

19.15 Remaining constraints from original handover

  • Feature manifests remain the canonical feature contract.
  • Background embedding generation must never block user writes.
  • Server Components are preferred for data-fetching.
  • Client Components should only exist where interactivity is required.
  • Drizzle must never execute in browser/client components.

20. Repository visibility

The GitHub repository is public. This is intentional, as the project is built in the open as a learning exercise and portfolio.

20.1 Why is this safe?

Security in this architecture comes from correct implementation, not obscurity. RLS policies enforce isolation, withApiGuard() centralizes authorization, API keys are hashed, and .env.local is gitignored.

20.2 Permanent caution—never commit secrets

We must never commit .env.local, Supabase service keys, API keys, or database credentials. If a secret is ever accidentally committed, it must be immediately rotated in the service dashboard—removing it from git history is insufficient.


21. Final architectural position

This architecture intentionally optimizes for:

  • Maintainability
  • Correctness
  • Solo-developer velocity
  • Future extensibility

While explicitly avoiding:

  • Premature microservices
  • Premature offline complexity
  • Runtime plugin overengineering
  • Unnecessary infrastructure

The system is designed to evolve safely over time without foundational rewrites.

Arkive

Index

Notes, decisions, and progress on my journey as I build Project Sidekick — built in the open; written as it happens.

Tags (145)

View

242 entries.

As ofTitleKind
2026-11-11Synergy Lesson 0 Walkthrough: One Repobuild walkthrough phase-3 monorepo one-repo git cloudflareguidance
2026-11-11Hosting and Domainssystem-design deployment vercel cloudflare domainspec
2026-11-11Synergy Lesson 0: One Repoplan phase-3 task monorepo one-repo git cloudflareplan
2026-11-11Synergy Checkpoint 3a: Prove the Store, Plan 3bplan phase-3 checkpoint guidanceplan
2026-11-11Synergy Lesson 1: Layer Folders and Lintplan phase-3 task monorepo eslintplan
2026-11-11Synergy - Feature Specificationsprd spec synergyprd
2026-11-11Agent Guideai-coding agent gateway agent-guidance rls supabase drizzle api react prettierguidance
2026-11-11Backlogged / Unplannedplan living-plan backlog feature-system taxila zinsser alter-ego parrot rls supabaseplan
2026-11-11Synergyplan living-plan phase-3 synergy rls postgresql api graphplan
2026-11-09Notesai-coding-harness agent-guidance nextjs eslint pnpm cssguidance
2026-11-08Synergy Lesson 4: Sandbox Providers and the First Routesplan phase-3 task synergy feature-system apiplan
2026-11-08Violations and Exceptionssystem-design synergyspec
2026-11-08Testing Layerssystem-design testing vitest playwrightspec
2026-11-08Best Practice Rulessystem-design code-quality-check eslintspec
2026-11-08Front Door: Hardening Walkthroughbuild walkthrough pre-2 rls supabase drizzle postgresql testing eslintguidance
2026-11-08Alter Egoplan living-plan phase-6 taxila zinsser alter-ego war-room factory core-driveplan
2026-11-08API Versioningsystem-design apispec
2026-11-08Approve Buildssystem-design monorepo nextjs pnpmspec
2026-11-08Best Practicesai-coding-harness agent-guidance drizzle api react pnpm css offline embedding soft-deleteguidance
2026-11-08Centralized Copysystem-design contentspec
2026-11-08dotenv CLIsystem-design config clispec
2026-11-08Installation at Workspace Levelsystem-design code-quality-check typescript pnpmspec
2026-11-08Pocketplan living-plan phase-8 taxila alter-ego nextjs vercel pwa mobileplan
2026-11-08Server Actionssystem-design nextjs rls api authenticationspec
2026-11-08Taxilaplan living-plan phase-4 taxila api-guard rls drizzle api authenticationplan
2026-11-08War Roomplan living-plan phase-7 war-room factory core-drive rls api offlineplan
2026-11-08With API Guardsystem-design security api-guard rls api authentication typescriptspec
2026-11-08Zinsserplan living-plan phase-5 taxila zinsser api mantine ai embeddingplan
2026-11-06Design Tokenssystem-design css design-systemspec
2026-11-06Native UIsystem-design css design-system mantinespec
2026-11-06Public Site: System Designsystem-design site one-repospec
2026-11-06Internationalizationsystem-design content i18nspec
2026-11-06Decisions Logdecisionlog
2026-11-06Synergy: System Designsystem-design synergyspec
2026-11-06CSS Modulessystem-design css eslint stylelintspec
2026-11-06Dependency Flowsystem-design monorepo clispec
2026-11-06ESLint Plugin Boundariessystem-design code-quality-check eslintspec
2026-11-06Non-Syncable Tablessystem-design database offlinespec
2026-11-06Prettier at Repo Levelsystem-design code-quality-check prettierspec
2026-11-06Runtime Validationssystem-design typescriptspec
2026-11-06Shared tsconfigsystem-design code-quality-check typescriptspec
2026-11-06Syncable Tablessystem-design database offline soft-deletespec
2026-11-06Technology Stacksystem-design supabase drizzle postgresql nextjs typescript turborepo pnpm vercelspec
2026-11-06Architectural OverviewReadingSidekick's architectural overview — an API-first platform tuned for solo developerssidekick project technical architecturedocument
2026-11-05One Repoprd feature synergy one-repoprd
2026-11-05Overview of Synergyprd feature synergyprd
2026-11-03Commands and Environmentai-coding command environment agent-guidance prettier pnpm cliguidance
2026-11-01Synergy Lesson 10: Save Call, Anchorsplan phase-3 task synergy apiplan
2026-11-01Synergy Lesson 11: Delete and Restoreplan phase-3 task synergy databaseplan
2026-11-01Synergy Lesson 12: Tagsplan phase-3 task synergy apiplan
2026-11-01Synergy Lesson 13: Race Testsplan phase-3 task synergy testing postgresqlplan
2026-11-01Synergy Lesson 2: Per-Package Migrationsplan phase-3 task database drizzle testingplan
2026-11-01Synergy Lesson 3: Entity Index and Version Logplan phase-3 task synergy database rls postgresqlplan
2026-11-01Synergy Lesson 5: Outbox, Status and Versionsplan phase-3 task synergy database postgresqlplan
2026-11-01Synergy Lesson 6: Links, Relation Types and Cyclesplan phase-3 task synergy graph postgresql apiplan
2026-11-01Synergy Lesson 7: Staleness Dots and the Roll-Upplan phase-3 task synergy apiplan
2026-11-01Synergy Lesson 8: Lists and Supersedeplan phase-3 task synergy graph postgresqlplan
2026-11-01Synergy Lesson 9: Save Call, Mentionsplan phase-3 task synergy apiplan
2026-11-01Content Sequencesystem-design synergyspec
2026-11-01Tombstone Visibilitysystem-design synergy rlsspec
2026-11-01Anchors in Contentsystem-design synergy anchorsspec
2026-11-01Capture External Contentsystem-design synergy taxilaspec
2026-11-01Lexicon Highlightingsystem-design synergy taxilaspec
2026-11-01Mentions and Link Lifetimesystem-design synergyspec
2026-11-01Synergy Store Choicessystem-design synergy postgresqlspec
2026-11-01Relationshipsprd feature synergyprd
2026-11-01Scope and Phasesprd feature synergyprd
2026-11-01Stay on ESLint, Revisit Oxlintsystem-design eslint typescriptspec
2026-11-01App Runtime for Drizzlesystem-design database drizzle postgresqlspec
2026-11-01Corepacksystem-design monorepo pnpmspec
2026-11-01Edge Runtimesystem-design security supabasespec
2026-11-01Env Vars in Turbo JSONsystem-design monorepo turborepo vercelspec
2026-11-01Flat Configsystem-design code-quality-check eslintspec
2026-11-01Force Dynamicsystem-design nextjs supabasespec
2026-11-01GraphQL and Relaysystem-design api graphql relayspec
2026-11-01Living Implementation Planplan living-plan taxila zinsser alter-ego war-room factory parrot core-driveplan
2026-11-01Module Resolution: Bundlersystem-design code-quality-check typescriptspec
2026-11-01Profile Creation Postgres Triggersystem-design security postgresql api authenticationspec
2026-11-01Public API Onlysystem-design api rls authentication clispec
2026-11-01tsupsystem-design code-quality-check eslintspec
2026-11-01Turboreposystem-design monorepo turborepo pnpmspec
2026-10-31Build mind palaceprd value-proposition specificationprd
2026-10-31Exponential Evolutionprd value-proposition specificationprd
2026-10-31Remember everythingprd value-proposition specificationprd
2026-10-31Entities and the Entity Indexprd feature synergyprd
2026-10-31Foundationsprd feature synergyprd
2026-10-31Keeping Links Trueprd feature synergyprd
2026-10-31Sneak Peek Linkprd feature synergyprd
2026-10-30Search and Backlinksprd feature synergyprd
2026-10-30Tagsprd feature synergyprd
2026-10-29Cost to Add Laterprinciple product engineeringguidance
2026-10-27Individual Firstprinciple productguidance
2026-10-27One Interfaceprinciple api cliguidance
2026-10-24Gatekeeper Lesson 7 Walkthrough: The Ops Package and Entitlements Grantbuild walkthrough phase-2 feature-system database postgresql cliguidance
2026-10-24Gatekeeper Lesson 8: Close-Outplan phase-2 task guidanceplan
2026-10-24Gatekeeper Walkthroughbuild walkthrough phase-2 api-guard feature-system rls authenticationguidance
2026-10-24Gatekeeper Lesson 3 Walkthrough: Entitlementsbuild walkthrough phase-2 feature-system database drizzle rls postgresql testingguidance
2026-10-24Gatekeeper Lesson 4 Walkthrough: withApiGuardbuild walkthrough phase-2 api-guard rls api authentication testingguidance
2026-10-24Gatekeeper Lesson 5 Walkthrough: Request and Auth-Failure Loggingbuild walkthrough phase-2 api-guard observability eslint testingguidance
2026-10-24Gatekeeper Lesson 6 Walkthrough: /api/health and Guard Verificationbuild walkthrough phase-2 api-guard api nextjs testingguidance
2026-10-24Gatekeeper Lesson 2 Walkthrough: resolveApiCallerbuild walkthrough phase-2 api-guard authentication supabase testingguidance
2026-10-24Gatekeeper Build Rules and Target Designplan phase-2 api-guard rls api authentication typescript guidanceplan
2026-10-24Gatekeeper Lesson 1 Walkthrough: Feature Registrybuild walkthrough phase-2 feature-system typescript monorepo testingguidance
2026-10-24Gatekeeper Lesson 7 (Task 2.10): Dev Entitlement Seed Scriptplan phase-2 task feature-system database postgresqlplan
2026-10-24Gatekeeperplan living-plan phase-2 api-guard rls api authentication feature-systemplan
2026-10-24Terminalplan living-plan phase-9 taxila api-guard rls api authentication cliplan
2026-10-23Gatekeeper Lesson 3 (Tasks 2.8, 2.9): Entitlements Table and getEnabledFeaturesplan phase-2 task feature-system database drizzle rls postgresql testingplan
2026-10-23Gatekeeper Lesson 4 (Tasks 2.2, 2.3): withApiGuard With withRLSplan phase-2 task api-guard rls api security testingplan
2026-10-23Gatekeeper Lesson 5 (Tasks 2.4, 2.5): Request and Auth-Failure Loggingplan phase-2 task api-guard observability eslintplan
2026-10-23Gatekeeper Lesson 6 (Tasks 2.11, 2.12): /api/health and Guard Verificationplan phase-2 task api-guard api nextjs testingplan
2026-10-23Centralizedsystem-design observability api authenticationspec
2026-10-23Database and Securityai-coding database security agent-guidance api-guard rls drizzle api react repository-patternguidance
2026-10-23Error Handlingsystem-design observability api-guard rls supabase api nextjs react aispec
2026-10-23Front Door: Row-Level Security Walkthroughplan phase-1.1 rls database supabase drizzle postgresql api typescriptguidance
2026-10-23Groundwork Checkpoint B Walkthroughbuild walkthrough phase-0 checkpointguidance
2026-10-20Gatekeeper Lesson 2 (Task 2.1): resolveApiCallerplan phase-2 task api-guard authentication supabase nextjsplan
2026-10-18Gatekeeper Lesson 1 (Tasks 2.6, 2.7): FeatureManifest and ALL_FEATURESplan phase-2 task feature-system typescript monorepoplan
2026-10-18Registrysystem-design feature-systemspec
2026-10-17Core Drive to Be Practical and Grounded in Realitysystem-design feature core-drive prdprd
2026-10-17MVP Scopeprd mvp specification core-drive taxila war-room factory alter-ego zinsser parrot api cli native-appprd
2026-10-17An AI Writing Coach and an Appsystem-design prd feature zinsser aiprd
2026-10-17Overview of Taxilasystem-design prd feature taxila ragprd
2026-10-16Front Door: Hardeningplan pre-2 foundation security database testingplan
2026-10-14Profiles Schemasystem-design security rls authenticationspec
2026-10-14Tag Taxonomyai-coding agent-guidance taxonomy discoveryguidance
2026-10-13Anatomy of a Core Drive Entrysystem-design prd feature core-driveprd
2026-10-13Core Drive Stores Personal and Sensitive Informationsystem-design prd feature core-drive taxila graphprd
2026-10-13Core Drive Stores Values Onlysystem-design prd feature core-drive war-room factoryprd
2026-10-13Core Drive to Foster Reflections and Learningssystem-design prd feature core-driveprd
2026-10-13Groundwork: Checkpointsplan phase-0 api nextjs typescript eslint turborepo pnpmplan
2026-10-13Model Routingprd vercel ai embedding routingprd
2026-10-13Overview of Core Drivesystem-design prd feature core-drive factory ai alter-egoprd
2026-10-13Source Attributionprd feature alter-ego aiprd
2026-10-12Command Paletteprd ux specificationprd
2026-10-12MVP Design Objectiveprd ux specificationprd
2026-10-12Be the Best Version of Yourselfprd value-proposition specificationprd
2026-10-12Make the Right Behavior Easierprd value-proposition specificationprd
2026-10-11Solve Problems and Build Thingsmotivation creativityjournal
2026-10-11A Personal Discoverymotivation discipline bucket-list ambition entrepreneurship sidekickjournal
2026-10-11Commercialize Sidekickmotivation finance freedomjournal
2026-10-10Realityprinciple reality pragmatism survivalguidance
2026-10-10Seek Closureprinciple productivity happiness purposeguidance
2026-10-08No Do-Oversprinciple core-drive execution productivityguidance
2026-10-08Pragmatismprinciple practical pragmaticguidance
2026-10-04Protect Your Mind and Your Timeprinciple productivity automation minimalismguidance
2026-10-03Focus Funnelprinciple core-drive productivityguidance
2026-10-02Fuel Career Growthmotivation career ambitionjournal
2026-10-02Learnmotivation learning ai ragjournal
2026-09-19Actual Stateglossary terminologyglossary
2026-09-19Algorithm of Lifeglossary terminology nextjsglossary
2026-09-19Alter Egosystem-design prd feature taxila alter-ego factory aiprd
2026-09-19API Firstsystem-design api clispec
2026-09-19Architectural Driverssystem-design offlinespec
2026-09-19Architecture Invariantsai-coding architecture invariant agent-guidance api nextjsguidance
2026-09-19Asynchronoussystem-design rag embeddingspec
2026-09-19Atomicsystem-design rag embeddingspec
2026-09-19Authenticationsystem-design security taxila api authentication pwa mobile clispec
2026-09-19Background Jobssystem-design vercel background-jobspec
2026-09-19Build for Today, Designed for Futuresystem-design offlinespec
2026-09-19Bundle Everythingsystem-design monorepospec
2026-09-19Capacitorsystem-design native-app nextjs mobile offlinespec
2026-09-19Centralizedsystem-design feature-systemspec
2026-09-19Centralized and Client-Agnosticsystem-design security rls api authentication clispec
2026-09-19CLIsystem-design cli apispec
2026-09-19Context Assemblersystem-design ai war-room factory api-guardspec
2026-09-19Coresystem-design feature-systemspec
2026-09-19Core Drive and Taxilasystem-design prd feature taxila core-driveprd
2026-09-19Driving Forces and Key Featuressystem-design api offlinespec
2026-09-19Embedding Status Fieldsystem-design rag embedding typescriptspec
2026-09-19Enforced Conventionssystem-designspec
2026-09-19Essential and Ideal Stateglossary terminologyglossary
2026-09-19Evolvabilitysystem-design rls offlinespec
2026-09-19Factorysystem-design prd feature factoryprd
2026-09-19Feature Package Workai-coding feature monorepo agent-guidance feature-systemguidance
2026-09-19Front Doorplan living-plan phase-1 api-guard rls supabase drizzle postgresql apiplan
2026-09-19Front Door Task 1.1plan phase-1 task supabase postgresql api authentication nextjsplan
2026-09-19Front Door Task 1.10plan phase-1 task rls supabase drizzle postgresql authentication typescriptplan
2026-09-19Front Door Task 1.11plan phase-1 task api-guard rls supabase api authentication nextjsplan
2026-09-19Front Door Task 1.14plan phase-1 task react pnpm mantine cssplan
2026-09-19Front Door Task 1.17plan phase-1 task supabase authenticationplan
2026-09-19Front Door Task 1.18plan phase-1 task api-guard rls supabase drizzle postgresql authenticationplan
2026-09-19Front Door Task 1.2plan phase-1 task supabase drizzle postgresql authentication nextjs pnpmplan
2026-09-19Front Door Task 1.3plan phase-1 task supabase nextjs typescriptplan
2026-09-19Front Door Task 1.4plan phase-1 task supabase authentication nextjs react typescriptplan
2026-09-19Front Door Task 1.5plan phase-1 task rls supabase authentication typescriptplan
2026-09-19Front Door Task 1.6plan phase-1 task rls supabase drizzle authentication typescript offlineplan
2026-09-19Front Door Task 1.7plan phase-1 task drizzle postgresql typescriptplan
2026-09-19Front Door Task 1.8plan phase-1 task turborepo pnpmplan
2026-09-19Front Door Task 1.9plan phase-1 task rls supabase drizzle postgresql authenticationplan
2026-09-19Front Door Tasks 1.12 and 1.13plan phase-1 task supabase api authentication nextjs react typescriptplan
2026-09-19Front Door Tasks 1.15 and 1.16plan phase-1 task supabase authentication nextjs react mantineplan
2026-09-19Front Door: Original Planplan phase-1 rls supabase drizzle postgresql authentication nextjsguidance
2026-09-19Front Door: Row-Level Securityplan living-plan phase-1.1 rls supabase drizzle postgresql pnpm soft-deleteplan
2026-09-19Groundworkplan living-plan phase-0 nextjs typescript eslint prettier turborepo pnpmplan
2026-09-19Groundwork Checkpoint Aplan phase-0 checkpoint nextjs typescript turborepo pnpm cliplan
2026-09-19Groundwork Checkpoint Bplan phase-0 checkpoint eslint prettier turborepo pnpmplan
2026-09-19Groundwork Checkpoint Cplan phase-0 checkpoint nextjs pnpmplan
2026-09-19Groundwork Checkpoint Dplan phase-0 checkpoint api-guard rls supabase drizzle api authenticationplan
2026-09-19Historic Stateglossary terminologyglossary
2026-09-19Idempotent APIsystem-design api idempotencyspec
2026-09-19Independent Deploymentssystem-design feature-systemspec
2026-09-19Informationglossary terminologyglossary
2026-09-19Instrumentationsystem-design observability vercel embeddingspec
2026-09-19Isolationsystem-design feature-systemspec
2026-09-19Lifecycle and Traceabilityprd governance planningguidance
2026-09-19Many Clients and Many Consumerssystem-design api pwa ai rag clispec
2026-09-19May Become Part of Taxilasystem-design core-drive taxilaspec
2026-09-19Middlewaresystem-design security api authenticationspec
2026-09-19Migrationsystem-design database drizzle pnpmspec
2026-09-19Model Router Contractsystem-design ai model-routing provider-agnostic embeddingspec
2026-09-19Never Mutate Outside API Layersystem-design apispec
2026-09-19Observabilitysystem-design api-guard api authentication vercel observabilityspec
2026-09-19Observablesystem-design rag embedding observabilityspec
2026-09-19Offline Readysystem-design api pwa offline soft-delete idempotencyspec
2026-09-19Open Houseplan living-plan phase-11plan
2026-09-19Parrotsystem-design prd feature parrotprd
2026-09-19Prefer JSON Configsystem-design monorepospec
2026-09-19Present Stateglossary terminologyglossary
2026-09-19Productivity Modulesystem-design prd feature war-roomprd
2026-09-19PWAsystem-design pwa offlinespec
2026-09-19RAGsystem-design rag ai embeddingspec
2026-09-19Repository Clientsystem-design database rls supabase drizzle api repository-patternspec
2026-09-19Request Flowsystem-design monorepo api offlinespec
2026-09-19Retryablesystem-design rag embeddingspec
2026-09-19Row-Level Securitysystem-design security rls drizzle offlinespec
2026-09-19Soft-Delete Supportsystem-design database soft-deletespec
2026-09-19Start Todayprinciple core-drive execution consistencyguidance
2026-09-19State Representationsystem-design api aispec
2026-09-19Storefrontplan living-plan phase-12 api offlineplan
2026-09-19Structured Response Attributionsystem-design ai structured-streaming source-attribution citationspec
2026-09-19System Overview Diagramsystem-designspec
2026-09-19Tiered Context Modelsystem-design core-drive domain situation war-room factory ai embeddingspec
2026-09-19Tiptap Requirementsystem-design rag embeddingspec
2026-09-19Use Navigation Hooksystem-design nextjsspec
2026-09-19Watchtowerplan living-plan phase-10 api-guard rls api authentication nextjs offlineplan
2026-07-19Project Sidekick - A Bird’s Eye ViewAn introduction to Project Sidekick. What is it? What problem does it solve? Why am I building it?sidekick project essaydocument
2026-07-10Building in the Margins of RealityProject kick-off post and a confessional essay about my past attempts and their failures. Why start now? What do I hope to achieve?sidekick project essayjournal
2026-05-29Config Files Explainedbuild walkthrough phase-0 turborepo typescript eslint prettierguidance
2026-05-29Front Door: Original Walkthroughbuild walkthrough phase-1 supabase drizzle authenticationguidance
2026-05-29Groundwork Checkpoint A Walkthroughbuild walkthrough phase-0 checkpointguidance
2026-05-29Groundwork Checkpoint C Walkthroughbuild walkthrough phase-0 checkpointguidance
2026-05-29Groundwork Checkpoint D Walkthroughbuild walkthrough phase-0 checkpointguidance