docs
Discussion summary
Historical architecture discussion notes from the earlier UI phase.
Architecture Discussion Summary
Note: Written for the earlier Svelte UI. For the current React + Tauri frontend, see frontend-react.
Your Key Requirements
- ✅ User defines initial conditions → Svelte UI forms → Tauri commands → Python computation
- ✅ Python handles computation → Python sidecar with CLI interface
- ✅ Persistent local storage → DuckDB + Parquet for time series
- ✅ YAML compatibility → Keep workspace/charts in YAML (same as Python package)
- ✅ 2-chart relations → Primary use case (transits, synastry)
- ✅ 3-body relations → Future-proof schema design
- ✅ Query-optimized → DuckDB indexes and Parquet partitioning
Architecture Decisions
Storage Strategy: Hybrid YAML + DuckDB
Why this approach:
- YAML for metadata: Charts, subjects, workspace config are human-readable and match Python package
- DuckDB for computed data: Fast queries on time series, efficient storage, SQL interface
- Parquet for archival: Long-term storage, columnar format, compression
Structure:
workspace/
├── workspace.yaml # Metadata (compatible with Python)
├── charts/*.yaml # Chart definitions
└── data/
├── workspace.db # DuckDB (positions, relations)
└── positions/*.parquet # Partitioned time series
Python Sidecar Performance
Performance considerations:
- Async communication: Tauri commands are async, Python runs in background
- Minimal overhead: Only serialization/deserialization cost
- Background processing: Long computations don’t block UI
- Caching: Store results in DuckDB, avoid recomputation
When to consider Rust port:
- If computation becomes bottleneck (>100ms per chart)
- If you need real-time updates (every second)
- If binary size is critical
Recommendation: Start with Python sidecar, measure performance, port only if needed.
Relation Structure
2-Chart Relations (Primary):
relations table:
- source_chart_id: Base chart (natal/event)
- target_chart_id: Transit chart (current time)
- relation_type: 'transit', 'synastry', 'progression'
3-Body Relations (Future):
relations table:
- source_chart_id: Chart 1
- target_chart_id: Chart 2
- third_chart_id: Chart 3 (optional)
- relation_type: 'composite_transit', 'triple_synastry', etc.
Aspect Computation:
- Aspects are computed on demand from stored positions
- No aspect tables or Parquet files are persisted
Main Date Table Structure
Core table: computed_positions
- Primary key:
(chart_id, datetime, object_id) - Indexes:
(chart_id, datetime),(object_id) - Stores: longitude, latitude, distance, speed, retrograde
Relation table: relations
- Links charts together
- Stores configuration snapshots (JSONB)
- Tracks computation settings (engine, ephemeris file)
Aspect data
- Derived at query time from
computed_positions
Date Format Handling
Storage:
- All dates stored as ISO 8601 strings or TIMESTAMP in DuckDB
- Original format preserved in chart YAML
Query:
- DuckDB handles timezone conversions
- Can query by any time format (converted to TIMESTAMP)
Example:
-- Store with original format metadata
INSERT INTO relations (..., original_date_format)
VALUES (..., 'julian_day', 2459845.5);
-- Query converts automatically
SELECT * FROM computed_positions
WHERE datetime >= '2024-01-01'::TIMESTAMP;
Source File Set (JPL/swisseph)
Storage:
enginecolumn: ‘jpl’, ‘swisseph’, ‘jyotish’, ‘custom’ephemeris_filecolumn: Path to BSP file (for JPL)- Stored per relation (can mix engines in same workspace)
Query:
-- Find all computations using de421.bsp
SELECT * FROM relations
WHERE engine = 'jpl' AND ephemeris_file LIKE '%de421%';
-- Get positions computed with specific engine
SELECT * FROM computed_positions
WHERE chart_id IN (
SELECT chart_id FROM relations WHERE engine = 'jpl'
);
Implementation Phases
Phase 1: Basic Chart Creation (Week 1-2)
- Tauri command:
create_chart() - Python CLI:
compute_positions - DuckDB schema setup
- Store single-timepoint positions
- Svelte UI: Chart creation form
Phase 2: Transit Computation (Week 3-4)
- Tauri command:
compute_transit_series() - Python CLI:
compute_transit_series - Background job tracking
- Store time series in DuckDB
- Svelte UI: Transit computation panel
Phase 3: Data Browsing (Week 5-6)
- Tauri commands:
query_positions(),query_aspects()(derived from positions) - DuckDB query optimization
- Svelte UI: Data tables, charts, filters
- Export functionality
Phase 4: Background Service (Week 7-8)
- Tauri background task system
- Job queue management
- Progress tracking
- Error handling and retry
Phase 5: Advanced Features (Week 9+)
- 3-body relations
- Parquet archival
- Performance optimization
- Rust porting (if needed)
Open Questions
1. Time Granularity
Question: What’s the minimum time step for transit computations?
Options:
- Hourly: Good for short-term transits (days/weeks)
- Daily: Good for long-term transits (months/years)
- Adaptive: Hourly for near-future, daily for far-future
Recommendation: Start with daily, add hourly option later.
2. Storage Limits
Question: How much historical data to keep?
Options:
- Unlimited: Store everything (requires good partitioning)
- Time-based: Keep last N years, archive older
- Size-based: Keep until database reaches X GB
Recommendation: Start unlimited, add archival later if needed.
3. Real-time Updates
Question: Should transits update in real-time or on-demand?
Options:
- On-demand: Compute when user requests
- Scheduled: Background service computes daily/hourly
- Hybrid: On-demand for new ranges, scheduled for updates
Recommendation: On-demand initially, add scheduled updates later.
4. Multi-workspace
Question: Support multiple workspaces simultaneously?
Options:
- Single: One workspace at a time (simpler)
- Multiple: Switch between workspaces (more complex)
Recommendation: Single workspace initially, add multi-workspace later.
5. Export Formats
Question: What formats for exporting computed data?
Options:
- CSV: Simple, universal
- JSON: Structured, easy to parse
- Parquet: Efficient, preserves types
- PDF: Human-readable reports
Recommendation: Start with CSV and JSON, add others as needed.
Next Steps
- Review this architecture - Does it match your vision?
- Answer open questions - Make decisions on granularity, storage, etc.
- Start Phase 1 - Implement basic chart creation
- Iterate - Build incrementally, test with real data
Key Files to Create
Rust (Tauri)
src-tauri/src/commands/compute.rs- Computation commandssrc-tauri/src/commands/workspace.rs- Workspace managementsrc-tauri/src/storage/duckdb.rs- DuckDB integrationsrc-tauri/src/storage/parquet.rs- Parquet file handling
Python
external_package/module/cli.py- CLI interface for Tauriexternal_package/module/storage.py- DuckDB helpers (optional)
TypeScript/Svelte
src/lib/stores/computations.ts- Computation statesrc/lib/stores/data.ts- Data queryingsrc/lib/components/TransitComputation.svelte- UI componentsrc/lib/components/DataBrowser.svelte- Data browsing UI
Questions for You
- Time granularity preference? (hourly, daily, adaptive)
- Storage limits? (unlimited, time-based, size-based)
- Real-time vs on-demand? (preference for transit updates)
- Multi-workspace needed? (now or later)
- Export format priority? (CSV, JSON, PDF, Parquet)
Once you answer these, we can finalize the architecture and start implementation!