Design Behind CapShip

The CapShip Code Tree

10,455 lines of typed React, TypeScript, and Python across 219 files. Skip weeks of native iOS/Android config, auth flows, and backend setup. run npx capship free/pro and start building your actual product on Day 1.

10,455 lines of typed React, TypeScript, and Python across 219 files. Skip weeks of native iOS/Android config, auth flows, and backend setup. run npx capship pro and start building your actual product on Day 1.

The Free & Pro Tree:

├── README.md

├── client

│ ├── capacitor.config.ts

│ ├── package-lock.json

│ ├── package.json

│ ├── postcss.config.js

│ ├── src

│ │ ├── api

│ │ │ ├── auth_api.ts

│ │ │ └── client.ts

│ │ ├── components

│ │ │ ├── shared

│ │ │ │ ├── app_boot_splash.tsx

│ │ │ │ ├── app_mark.tsx

│ │ │ │ ├── back_icon_button.tsx

│ │ │ │ ├── dashboard_nav_config.ts

│ │ │ │ ├── dashboard_route_loader.tsx

│ │ │ │ ├── dashboard_skeletons.tsx

│ │ │ │ ├── error_alert.tsx

│ │ │ │ ├── loading_spinner.tsx

│ │ │ │ ├── mobile_bottom_nav.tsx

│ │ │ │ ├── oauth_buttons.tsx

│ │ │ │ ├── offline_dashboard_state.tsx

│ │ │ │ ├── page_loader.tsx

│ │ │ │ ├── route_title.tsx

│ │ │ │ ├── segmented_control.tsx

│ │ │ │ ├── session_expired_overlay.tsx

│ │ │ │ └── top_nav.tsx

│ │ │ └── ui

│ │ │ ├── alert-dialog.tsx

│ │ │ ├── avatar.tsx

│ │ │ ├── badge.tsx

│ │ │ ├── button.tsx

│ │ │ ├── dialog.tsx

│ │ │ ├── dropdown-menu.tsx

│ │ │ ├── input-otp.tsx

│ │ │ ├── input.tsx

│ │ │ ├── select.tsx

│ │ │ ├── skeleton.tsx

│ │ │ ├── toast.tsx

│ │ │ └── toaster.tsx

│ │ ├── controllers

│ │ │ ├── app_boot_controller.ts

│ │ │ ├── auth_controller.ts

│ │ │ ├── cache_orchestrator.ts

│ │ │ ├── dashboard_controller.ts

│ │ │ └── profile_bootstrap.ts

│ │ ├── hooks

│ │ │ ├── use-toast.ts

│ │ │ ├── use_document_title.ts

│ │ │ ├── use_network_status.ts

│ │ │ └── use_typing_effect.ts

│ │ ├── layouts

│ │ │ ├── auth_layout.tsx

│ │ │ └── dashboard_layout.tsx

│ │ ├── lib

│ │ │ ├── animation_constants.ts

│ │ │ ├── auth_tokens.ts

│ │ │ ├── capship_realtime.ts

│ │ │ ├── constants.ts

│ │ │ ├── idempotency.ts

│ │ │ ├── input_attributes.ts

│ │ │ ├── native_apple_sign_in.ts

│ │ │ ├── native_oauth.ts

│ │ │ ├── timezones.ts

│ │ │ └── utils.ts

│ │ ├── main.tsx

│ │ ├── pages

│ │ │ ├── auth

│ │ │ │ └── account_deleted_page.tsx

│ │ │ ├── dashboard

│ │ │ │ ├── page1

│ │ │ │ │ └── page1.tsx

│ │ │ │ ├── page2

│ │ │ │ │ └── page2.tsx

│ │ │ │ ├── page3

│ │ │ │ │ └── page3.tsx

│ │ │ │ ├── page4

│ │ │ │ │ └── page4.tsx

│ │ │ │ ├── profile

│ │ │ │ │ └── profile_page.tsx

│ │ │ │ └── settings

│ │ │ │ ├── delete

│ │ │ │ │ └── delete_account_page.tsx

│ │ │ │ └── settings_page.tsx

│ │ │ ├── legal

│ │ │ │ ├── privacy_policy_page.tsx

│ │ │ │ └── terms_of_service_page.tsx

│ │ │ ├── login

│ │ │ │ └── login_page.tsx

│ │ │ └── otp

│ │ │ └── otp_page.tsx

│ │ ├── router

│ │ │ ├── index.tsx

│ │ │ ├── private_guard.tsx

│ │ │ ├── public_guard.tsx

│ │ │ └── use_session_check.ts

│ │ ├── store

│ │ │ ├── auth_store.ts

│ │ │ ├── dashboard_store.ts

│ │ │ └── ui_store.ts

│ │ ├── types

│ │ │ ├── auth_types.ts

│ │ │ ├── authentication_types.ts

│ │ │ ├── base_types.ts

│ │ │ └── store_types.ts

│ │ └── vite-env.d.ts

│ ├── tailwind.config.js

│ ├── tsconfig.app.json

│ ├── tsconfig.node.json

│ └── vite.config.ts

└── server

├── .env

├── __init__.py

├── data

│ ├── cloudflare_ips.json

│ ├── disposable_emails.bin

│ └── geoip.mmdb

├── main.py

└── src

├── app

│ ├── config

│ │ ├── apple_http.py

│ │ ├── cache_manager.py

│ │ ├── cloudflare_ip_ranges.py

│ │ ├── db_client.py

│ │ ├── email_templates.py

│ │ ├── geoip_client.py

│ │ ├── google_http.py

│ │ ├── http_client.py

│ │ ├── jwks.py

│ │ ├── lua_manager.py

│ │ ├── redis_client.py

│ │ ├── redis_pubsub_client.py

│ │ └── settings.py

│ ├── crons

│ │ └── refresh_cloudflare_ips.py

│ ├── crypto

│ │ ├── encryption

│ │ │ ├── aes_decrypt.py

│ │ │ ├── aes_encrypt.py

│ │ │ └── hash_blake2s.py

│ │ ├── ids.py

│ │ ├── secrets

│ │ │ └── generate_otp.py

│ │ └── tokens

│ │ ├── event_tokens.py

│ │ ├── provider_tokens.py

│ │ └── session_tokens.py

│ ├── errors

│ │ ├── base.py

│ │ ├── domains

│ │ │ └── authentication_errors.py

│ │ └── handler.py

│ ├── events

│ │ ├── event_consumer.py

│ │ ├── event_emitter.py

│ │ └── pubsub

│ │ ├── event_publisher.py

│ │ └── event_subscriber.py

│ ├── logging

│ │ ├── logger_config.py

│ │ └── logger_setup.py

│ ├── middleware

│ │ ├── middleware_chain.py

│ │ ├── phases

│ │ │ ├── phase1

│ │ │ │ ├── endpoint_matrix.py

│ │ │ │ ├── execute.py

│ │ │ │ ├── extract_identity.py

│ │ │ │ ├── helpers

│ │ │ │ │ ├── classify_ip_type.py

│ │ │ │ │ └── extract_country.py

│ │ │ │ └── request_context.py

│ │ │ ├── phase2

│ │ │ │ └── execute.py

│ │ │ └── phase3

│ │ │ └── execute.py

│ │ └── security

│ │ ├── execute.py

│ │ ├── rate_limiting

│ │ │ └── check_rate_limit.py

│ │ └── web

│ │ ├── cors_handler.py

│ │ ├── csp_handler.py

│ │ └── response_headers.py

│ ├── routers

│ │ ├── authentication

│ │ │ ├── auth_router.py

│ │ │ └── cookie_policy.py

│ │ ├── classes

│ │ │ ├── authentication_classes.py

│ │ │ └── base.py

│ │ ├── dependencies

│ │ │ └── router_dependencies.py

│ │ ├── health.py

│ │ └── realtime

│ │ ├── helpers

│ │ │ └── connection_registry.py

│ │ └── realtime_router.py

│ ├── start

│ │ ├── app.py

│ │ ├── context.py

│ │ ├── lua.py

│ │ ├── middleware.py

│ │ └── worker.py

│ └── validation

│ ├── validate_email.py

│ └── validate_username.py

├── logic

│ ├── authentication

│ │ ├── deletion

│ │ │ ├── complete_deletion.py

│ │ │ └── initiate_deletion.py

│ │ ├── login

│ │ │ └── oauth

│ │ │ ├── apple

│ │ │ │ └── complete_apple_oauth.py

│ │ │ ├── complete_oauth.py

│ │ │ ├── google

│ │ │ │ └── complete_google_oauth.py

│ │ │ └── identity.py

│ │ ├── logout

│ │ │ └── logout.py

│ │ ├── profile

│ │ │ ├── update_profile_name.py

│ │ │ └── update_profile_timezone.py

│ │ └── shared

│ │ ├── bootstrap_new_user.py

│ │ ├── issue_session.py

│ │ ├── resolve_current_user.py

│ │ ├── send_email.py

│ │ └── ui

│ │ └── get_auth_functions.py

│ └── workers

│ ├── handle_dummy_email 2.py

│ ├── handle_dummy_email.py

│ ├── handle_email 2.py

│ ├── handle_email.py

│ ├── helper

│ │ ├── apply_events_for_match.py

│ │ ├── apply_team_roster.py

│ │ ├── log_roster_sync_error_once.py

│ │ ├── process_due_match_sync_jobs.py

│ │ ├── process_due_team_roster_sync_jobs.py

│ │ ├── settle_due_matches.py

│ │ ├── sports_sync_constants.py

│ │ ├── sports_sync_schedule.py

│ │ └── sync_fixtures_if_due.py

│ ├── redis

│ │ ├── handle_session_expire.py

│ │ ├── handle_session_hash_expire.py

│ │ ├── handle_user_sessions_expire.py

│ │ ├── handle_user_sessions_expire_except.py

│ │ └── session_expire_retries.py

│ ├── session_memory_invalidation_listener 2.py

│ ├── session_memory_invalidation_listener.py

│ ├── worker_event_loop 2.py

│ └── worker_event_loop.py

├── scripts

│ ├── bundle_codebase.py

│ └── organize_imports.py

└── store

├── cache

│ ├── authentication

│ │ ├── expire_all_redis_sessions.py

│ │ ├── expire_all_redis_sessions_except.py

│ │ ├── expire_redis_session.py

│ │ ├── expire_redis_session_by_hash.py

│ │ ├── memory

│ │ │ ├── rate_limit_memory_cache.py

│ │ │ └── session_memory_cache.py

│ │ ├── pending_deletion.py

│ │ ├── set_redis_session.py

│ │ ├── store_otp.py

│ │ └── verify_otp.py

│ └── idempotency.py

└── sql

└── authentication

├── sessions

│ ├── expire_all_sessions.py

│ ├── expire_session.py

│ ├── insert_session.py

│ ├── select_session_by_token_hash.py

│ ├── shared

│ │ └── resolve_session_by_token_hash.py

│ └── ui

│ └── get_all_user_sessions.py

└── users

├── bind_oauth_subject.py

├── insert_name.py

├── insert_user.py

├── select_authenticated_user.py

├── select_profile_mutation_state.py

├── select_user_by_email_hash.py

├── select_user_by_id.py

├── soft_delete_user.py

├── ui

│ └── get_all_user_profile.py

├── update_name.py

├── update_provider_refresh_token.py

└── update_timezone.py