Arkive

Architectural Overview

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

As of
Version2.1.0
Kinddocument, for software engineers
Length4,836 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

Clients Browser | PWA | CLI | Agents | iOS API Layer (/api/*) withApiGuard() ├── Auth ├── Feature Entitlement ├── RLS Context ├── Scope Validation └── Handler Execution PostgreSQL (Supabase) RLS Policies Feature Tables Vector Search

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.

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

ModulePurposePackageMVP
TaxilaKnowledge management: atomic notes + knowledge sources (live links, captured content, markdown), metadata enrichment, RAG substratepackages/feature-taxilaYes
ZinsserWriting app + AI writing coach trained on the user's own stylepackages/feature-zinsserYes (editor first; coach after AI layer)
Core DriveThe value system: principles, mental models, priorities, plans — context layer for all AI featurespackages/feature-core-driveYes
Alter EgoAI confidant grounded in Core Drive + Taxilapackages/feature-alter-egoYes
War RoomPlanning and strategy (tasks, day planning)packages/feature-war-roomYes
FactoryExecution and automation. MVP scope: push-button workflows + configurable input defaultspackages/feature-factoryPartial
ParrotVoice 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:

CategoryNatureLoading behavior
IdentityWho the user is, brief historyKernel (always loaded)
PrinciplesUniversal truths ("No do-overs") — apply almost everywhereKernel (always loaded)
Communication stylesHow the user prefers to communicate and writeKernel (always loaded)
Mental modelsSituational algorithms ("never shop hungry" → spending tasks only)By applicability metadata
HeuristicsMental shortcuts for low-consequence situationsBy applicability metadata
Tools & systemsThe user's day-to-day toolchainBy applicability metadata
Preferences & constraintsStanding preferences and hard limitsBy applicability metadata
Domain knowledgeSubject-matter knowledgeLives 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 a GraphRepository in packages/core — 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 an entity type in packages/features-registry — the registry doubles as the entity-type ledger.
  2. The edges table (fromId, fromType, toId, toType, relation, timestamps) lives in packages/core. Core stays feature-agnostic because it stores opaque typed IDs, never feature schemas.
  3. Global tags and entity_tags 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

LayerChoice
FrontendNext.js 16 App Router
LanguageTypeScript Strict
DBSupabase PostgreSQL
ORMDrizzle ORM
StylingMantine
EditorTiptap
AI SDKVercel AI SDK
LLMProvider-agnostic router (default: Anthropic Claude)
EmbeddingsOpenAI text-embedding-3-small
MonorepoTurborepo + pnpm
HostingVercel
Native ShellCapacitor

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).

CommandUSING applies?WITH CHECK applies?
SELECTYes—
INSERT—Yes
UPDATEYes (which rows you may update)Yes (what the row may become)
DELETEYes—
MEANINGfilters existing rows to prevent unauthorized operationsvalidates 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

ConstraintMechanismEnforced at
User sees only their own rowsRLS USING clauseDatabase
Soft-deleted rows invisible to usersRLS USING clauseDatabase
Hard deletes blockedBEFORE DELETE triggerDatabase
Updates on deleted rows blockedBEFORE UPDATE triggerDatabase
SELECT filtering (belt)where(isNull(deletedAt)) in reposApplication

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 clientDrizzle client
await admin.from('notes').select('*');db.select().from(table);
Executed as SELECT * FROM notesSELECT * FROM notes WHERE deleted_at IS NULL AND user_id = <userId>
superuser roleapp_runtime - non-superuser role
No RLSEnforces RLS
Enforces triggersEnforces 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?

(Pending implementation details)

10.2 How withAPIGuard will be used?

(Pending implementation details)


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 allowed as long as they 1) pass through repositories, 2) do not bypass APIs, and 3) do not bypass authorization checks. This ensures our API-first guarantee.


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.js, 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 Inggest, 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

ClientFileKeyUsed In
createBrowserClient()browser.tspublishable keyClient Components ('use client')
createServerClient()server.tspublishable key + cookiesServer Components, Route Handlers (Node.js runtime)
createProxyClient(req, res)proxy.tspublishable key + request cookiesproxy.ts only (Edge runtime)
createAdminClient()admin.tssecret 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

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 uses CSS modules without exception. 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.

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. Monorepo foundation ✅
  2. Auth + security shell (incl. DB-level RLS enforcement) ✅
  3. Core infrastructure — withApiGuard + feature system
  4. Graph store & metadata service
  5. Taxila v1 (+ command-palette shell)
  6. Zinsser v1 (editor)
  7. Core Drive + AI layer + Alter Ego
  8. War Room + Factory v1 (push-button workflows)
  9. PWA & native shell
  10. API keys & CLI
  11. Observability & hardening
  12. Dogfooding, then billing (optional — not a product goal per PRD)

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 (125)

View

208 entries.

As ofTitleKind
2026-10-03Focus Funnelprinciple core-drive productivityguidance
2026-10-02A Personal Discoverymotivationguidance
2026-10-02Commercialize Sidekickmotivationguidance
2026-10-02Fuel Career Growthmotivationguidance
2026-10-02Learn as I Build This Productmotivation ai ragguidance
2026-10-02Coding Agent HeuristicsRetiredWhich AI model or coding agent to use for which kind of session based on the type of task, teaching value, and complexitysidekick project technical ai heuristicnote
2026-09-20Pre 2 foundation hardeningplan pre-2 foundation security database testingplan
2026-09-19A graph pattern not a graph databasesystem-design global-tagging-and-linking postgresql graphspec
2026-09-19Actual stateglossary terminologyglossary
2026-09-19Agent guideai-coding agent gateway agent-guidance rls supabase drizzle api react prettierguidance
2026-09-19Algorithm of lifeglossary terminology nextjsglossary
2026-09-19Alter egosystem-design prd feature taxila alter-ego factory aiprd
2026-09-19Anatomy of a core drive entrysystem-design prd feature core-driveprd
2026-09-19API firstsystem-design api clispec
2026-09-19API route fail openopportunity phase-2 api security eslint severity-lowopportunity
2026-09-19API versioningsystem-design apispec
2026-09-19App runtime for Drizzlesystem-design database drizzle postgresqlspec
2026-09-19App runtime role for Drizzledecision technical architecture-decision rls supabase drizzledecision
2026-09-19Approve buildssystem-design monorepo nextjs pnpmspec
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-19Backlogged unplannedplan living-plan backlog taxila zinsser alter-ego parrot rls supabaseplan
2026-09-19Best practicesai-coding-harness agent-guidance drizzle api react pnpm css offline embedding soft-deleteguidance
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-19Centralizedsystem-design observability api authenticationspec
2026-09-19Centralized and client agnosticsystem-design security rls api authentication clispec
2026-09-19Centralized copydecision technical architecture-decision authentication typescript clidecision
2026-09-19Centralized copysystem-design contentspec
2026-09-19Checkpoint aplan phase-0 checkpoint nextjs typescript turborepo pnpm cliplan
2026-09-19Checkpoint bplan phase-0 checkpoint eslint prettier turborepo pnpmplan
2026-09-19Checkpoint cplan phase-0 checkpoint nextjs pnpmplan
2026-09-19Checkpoint dplan phase-0 checkpoint api-guard rls supabase drizzle api authenticationplan
2026-09-19CLIsystem-design cli apispec
2026-09-19Commands and environmentai-coding command environment agent-guidance prettier pnpm cliguidance
2026-09-19Context assemblersystem-design ai war-room factory api-guardspec
2026-09-19Coresystem-design feature-systemspec
2026-09-19Core drive vs Taxilasystem-design prd feature taxila core-driveprd
2026-09-19Corepacksystem-design monorepo pnpmspec
2026-09-19CSS modulessystem-design css eslint mantinespec
2026-09-19Database and securityai-coding database security agent-guidance api-guard rls drizzle api react repository-patternguidance
2026-09-19DB access chokepointopportunity phase-2 database rls architecture severity-highopportunity
2026-09-19Dependency flowsystem-design monorepo clispec
2026-09-19Design constraintssystem-design global-tagging-and-linking rls offline soft-deletespec
2026-09-19dotenv CLIdecision technical architecture-decision clidecision
2026-09-19dotenv CLIsystem-design config clispec
2026-09-19Driving forces and key featuressystem-design api offlinespec
2026-09-19Edge runtimedecision technical architecture-decision supabase api nextjsdecision
2026-09-19Edge runtimesystem-design security supabasespec
2026-09-19Embedding status fieldsystem-design rag embedding typescriptspec
2026-09-19Enforced conventionssystem-designspec
2026-09-19Env vars in turbo JSONdecision technical architecture-decision turborepo verceldecision
2026-09-19Env vars in turbo JSONsystem-design monorepo turborepo vercelspec
2026-09-19Environment contract driftopportunity phase-2 config security developer-experience severity-mediumopportunity
2026-09-19Error handlingsystem-design observability api-guard rls supabase api nextjs react aispec
2026-09-19ESLint plugin boundariessystem-design code-quality-check eslintspec
2026-09-19ESLint rules to use tsupdecision technical architecture-decision nextjs eslintdecision
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-19Flat configdecision technical architecture-decision typescript eslintdecision
2026-09-19Flat configsystem-design code-quality-check eslintspec
2026-09-19Force dynamicdecision technical architecture-decision supabase authentication nextjsdecision
2026-09-19Force dynamicsystem-design nextjs supabasespec
2026-09-19Global tags and metadatasystem-design global-tagging-and-linking taxila zinsser alter-ego war-room factory core-drivespec
2026-09-19GraphQL and Relaysystem-design api graphql relayspec
2026-09-19GraphQL Relaydecision technical architecture-decision api-guard rls supabase drizzle api authentication nextjsdecision
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-19Installation at workspace levelsystem-design code-quality-check typescript pnpmspec
2026-09-19Instrumentationsystem-design observability vercel embeddingspec
2026-09-19Interaction modelprd ux specificationprd
2026-09-19Isolationsystem-design feature-systemspec
2026-09-19Lifecycle and traceabilityprd governance planningguidance
2026-09-19Living implementation planplan living-plan taxila zinsser alter-ego war-room factory parrot core-driveplan
2026-09-19Make right behavior easierprd value-proposition specificationprd
2026-09-19Mantinesystem-design css mantinespec
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-19Model routingprd feature vercel ai embedding model-routingprd
2026-09-19Module resolution bundlerdecision technical architecture-decision nextjs typescriptdecision
2026-09-19Module resolution bundlersystem-design code-quality-check typescriptspec
2026-09-19Narrow the gapprd value-proposition specificationprd
2026-09-19Never mutate outside API layersystem-design apispec
2026-09-19No API versioningdecision technical architecture-decision api-guard api nextjs clidecision
2026-09-19No Do-oversprinciple core-drive anti-abandonment execution productivityguidance
2026-09-19No utility stylesdecision technical architecture-decision eslint mantine cssdecision
2026-09-19Non syncable tablessystem-design database offlinespec
2026-09-19Notesai-coding-harness agent-guidance nextjs eslint pnpm cssguidance
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-19Package boundary enforcementopportunity phase-2 monorepo eslint architecture severity-mediumopportunity
2026-09-19Parrotsystem-design prd feature parrotprd
2026-09-19Phase 0 foundation and toolingplan phase-0 api nextjs typescript eslint turborepo pnpmguidance
2026-09-19Phase 0 foundation tooling completeplan living-plan phase-0 nextjs typescript eslint prettier turborepo pnpmplan
2026-09-19Phase 1 Supabase and auth shellplan phase-1 rls supabase drizzle postgresql authentication nextjsguidance
2026-09-19Phase 1 Supabase auth shell completeplan living-plan phase-1 api-guard rls supabase drizzle postgresql apiplan
2026-09-19Phase 1.1 DB level RLS soft delete enforcement completeplan living-plan phase-1.1 rls supabase drizzle postgresql pnpm soft-deleteplan
2026-09-19Phase 1.1 DB RLS enforcementplan phase-1.1 rls database supabase drizzle postgresql api typescriptguidance
2026-09-19Phase 10 observability hardeningplan living-plan phase-10 api-guard rls api authentication nextjs offlineplan
2026-09-19Phase 11 dogfooding friends family access optionalplan living-plan phase-11plan
2026-09-19Phase 12 billing SaaS readiness optional pathplan living-plan phase-12 api offlineplan
2026-09-19Phase 2 core infrastructure API guard feature systemplan living-plan phase-2 api-guard rls api authentication feature-systemplan
2026-09-19Phase 3 graph store metadata serviceplan living-plan phase-3 api-guard rls postgresql api offline graphplan
2026-09-19Phase 4 Taxila v1 knowledge managementplan living-plan phase-4 taxila api-guard rls drizzle api authenticationplan
2026-09-19Phase 5 Zinsser v1 writing editor firstplan living-plan phase-5 taxila zinsser api mantine ai embeddingplan
2026-09-19Phase 6 core drive AI layer alter egoplan living-plan phase-6 taxila zinsser alter-ego war-room factory core-driveplan
2026-09-19Phase 7 war room factory v1plan living-plan phase-7 war-room factory core-drive rls api offlineplan
2026-09-19Phase 8 PWA iOS shellplan living-plan phase-8 taxila alter-ego nextjs vercel pwa mobileplan
2026-09-19Phase 9 API keys CLIplan living-plan phase-9 taxila api-guard rls api authentication cliplan
2026-09-19Pooler client configurationopportunity phase-2 database supabase drizzle severity-mediumopportunity
2026-09-19Portable documentation vaultopportunity documentation agentic-coding portability severity-mediumopportunity
2026-09-19Post mvp factory extensions bots agentsplan living-plan backlog factory parrot api-guard rls supabase drizzleplan
2026-09-19Pragmatism and Balanceprincipleguidance
2026-09-19Prd.value proposition.be better version of yourselfprd value-proposition specificationprd
2026-09-19Prefer JSON configsystem-design monorepospec
2026-09-19Present stateglossary terminologyglossary
2026-09-19Prettier at repo levelsystem-design code-quality-check prettierspec
2026-09-19Private informationsystem-design prd feature core-drive taxila graphprd
2026-09-19Profile creation Postgres triggersystem-design security postgresql api authenticationspec
2026-09-19Profile trigger and referential integrityopportunity phase-2 database authentication integrity severity-highopportunity
2026-09-19Profiles schemasystem-design security rls authenticationspec
2026-09-19Protect your mind and your timeprinciple productivity core-driveguidance
2026-09-19Public API onlysystem-design api rls authentication clispec
2026-09-19PWAsystem-design pwa offlinespec
2026-09-19RAGsystem-design rag ai embeddingspec
2026-09-19Realityprincipleguidance
2026-09-19Reflections and learningssystem-design prd feature core-driveprd
2026-09-19Registrysystem-design feature-systemspec
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-19Runtime database URL driftopportunity phase-2 security rls config severity-highopportunity
2026-09-19Runtime role reproducibilityopportunity phase-2 database security severity-criticalopportunity
2026-09-19Runtime validationsdecision technical architecture-decision api-guard supabase api typescript clidecision
2026-09-19Runtime validationssystem-design typescriptspec
2026-09-19Security proof and ciopportunity phase-2 testing ci security severity-highopportunity
2026-09-19Seek closureprinciple core-drive execution realityguidance
2026-09-19Server actionssystem-design nextjs rls api authenticationspec
2026-09-19Shared tsconfigdecision technical architecture-decision nextjs clidecision
2026-09-19Shared tsconfigsystem-design code-quality-check typescriptspec
2026-09-19Signup confirmation flowopportunity authentication ux severity-lowopportunity
2026-09-19Soft delete supportsystem-design database soft-deletespec
2026-09-19Source attributionprd feature alter-ego aiprd
2026-09-19Start todayprinciple core-drive execution consistencyguidance
2026-09-19State representationsystem-design api aispec
2026-09-19Structured response attributionsystem-design ai structured-streaming source-attribution citationspec
2026-09-19Syncable tablessystem-design database offline soft-deletespec
2026-09-19System overview diagramsystem-designspec
2026-09-19Tag taxonomyai-coding agent-guidance taxonomy discoveryguidance
2026-09-19Task 1.1plan phase-1 task supabase postgresql api authentication nextjsplan
2026-09-19Task 1.10plan phase-1 task rls supabase drizzle postgresql authentication typescriptplan
2026-09-19Task 1.11plan phase-1 task api-guard rls supabase api authentication nextjsplan
2026-09-19Task 1.12and1.13plan phase-1 task supabase api authentication nextjs react typescriptplan
2026-09-19Task 1.14plan phase-1 task react pnpm mantine cssplan
2026-09-19Task 1.15and1.16plan phase-1 task supabase authentication nextjs react mantineplan
2026-09-19Task 1.17plan phase-1 task supabase authenticationplan
2026-09-19Task 1.18plan phase-1 task api-guard rls supabase drizzle postgresql authenticationplan
2026-09-19Task 1.2plan phase-1 task supabase drizzle postgresql authentication nextjs pnpmplan
2026-09-19Task 1.3plan phase-1 task supabase nextjs typescriptplan
2026-09-19Task 1.4plan phase-1 task supabase authentication nextjs react typescriptplan
2026-09-19Task 1.5plan phase-1 task rls supabase authentication typescriptplan
2026-09-19Task 1.6plan phase-1 task rls supabase drizzle authentication typescript offlineplan
2026-09-19Task 1.7plan phase-1 task drizzle postgresql typescriptplan
2026-09-19Task 1.8plan phase-1 task turborepo pnpmplan
2026-09-19Task 1.9plan phase-1 task rls supabase drizzle postgresql authenticationplan
2026-09-19Taxilasystem-design prd feature taxila ragprd
2026-09-19Technology stacksystem-design supabase drizzle postgresql nextjs typescript turborepo pnpm vercelspec
2026-09-19Tiered context modelsystem-design core-drive domain situation war-room factory ai embeddingspec
2026-09-19Tiptap requirementsystem-design rag embeddingspec
2026-09-19tsupsystem-design code-quality-check eslintspec
2026-09-19Turboreposystem-design monorepo turborepo pnpmspec
2026-09-19TypeScript hoistingdecision technical architecture-decision nextjs typescript pnpmdecision
2026-09-19Use corepackdecision technical architecture-decision pnpm verceldecision
2026-09-19Use navigation hooksystem-design nextjsspec
2026-09-19User profile creation by DB triggerdecision technical architecture-decision supabase api authenticationdecision
2026-09-19Values onlysystem-design prd feature core-drive war-room factoryprd
2026-09-19Verceldecision technical architecture-decision nextjs turborepo pnpm verceldecision
2026-09-19Vercelsystem-design monorepo turborepo pnpm vercelspec
2026-09-19War roomsystem-design prd feature war-roomprd
2026-09-19What is itsystem-design prd feature core-drive factory aiprd
2026-09-19Why Prettier at repo level?decision technical architecture-decision prettier turborepo graphdecision
2026-09-19Why Turborepodecision technical architecture-decision turborepo pnpmdecision
2026-09-19With API guardsystem-design security api-guard rls api authentication typescriptspec
2026-09-19Zinssersystem-design prd feature zinsser aiprd
2026-08-24Architectural OverviewReadingSidekick's architectural overview — an API-first platform tuned for solo developerssidekick project technical architecturedocument
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-29Checkpoint A walkthroughbuild walkthrough phase-0 checkpointguidance
2026-05-29Checkpoint B walkthroughbuild walkthrough phase-0 checkpointguidance
2026-05-29Checkpoint C walkthroughbuild walkthrough phase-0 checkpointguidance
2026-05-29Checkpoint D walkthroughbuild walkthrough phase-0 checkpointguidance
2026-05-29Config files explainedbuild walkthrough phase-0 turborepo typescript eslint prettierguidance
2026-05-29Phase 1 walkthroughbuild walkthrough phase-1 supabase drizzle authenticationguidance