diff --git a/.claude/skills/astrodb-website/SKILL.md b/.claude/skills/astrodb-website/SKILL.md new file mode 100644 index 0000000..fa6eb42 --- /dev/null +++ b/.claude/skills/astrodb-website/SKILL.md @@ -0,0 +1,84 @@ +--- +name: astrodb-website +description: Set up and run a web interface for an AstroDB database using the Astro-Web template. Use this skill whenever a user wants to "view the database in a browser", "start the web interface", "see the data", or "set up the website". +compatibility: python, fastapi, uvicorn +--- + +# AstroDB Website + +This skill sets up a FastAPI web interface ([Astro-Web](https://github.com/astrodbtoolkit/Astro-Web)) in your project directory to browse and visualize an AstroDB SQLite database. + +## Prerequisites + +- An existing AstroDB SQLite database (`.sqlite` or `.db`). +- `uv` installed. +- Python 3.13+. + +## Step 1: Clone the Astro-Web Repository + +The website should be set up in a directory named `website/` (or similar) in your project root. If it doesn't exist, clone it: + +```bash +git clone https://github.com/astrodbtoolkit/Astro-Web website +``` + +Or, if the user prefers a submodule: +```bash +git submodule add https://github.com/astrodbtoolkit/Astro-Web website +``` + +## Step 2: Set up the Website Configuration + +Use the bundled setup script to generate the `.env` file. You must point it to the database file and the directory where you cloned the website. + +### Step 2.1: Verify Table and Column Names (Crucial) + +Before running the setup script, verify the primary table name and coordinate columns: + +1. **Check for primary table**: Run `sqlite3 .sqlite ".tables"` + - If a table named `Sources` or `sources` is not found, **ask the user** what the primary sources table is. +2. **Check coordinate columns**: Run `sqlite3 .sqlite "PRAGMA table_info();"` + - Identify the RA and Dec column names (e.g., `ra` vs `ra_deg`). + +### Step 2.2: Run Setup Script + +Run the script with the verified table and column names: + +```bash +uv run python .claude/skills/astrodb-website/scripts/setup_website.py \ + --db-path .sqlite \ + --website-dir website/ \ + --primary-table \ + --ra-col \ + --dec-col +``` + +The script will: +1. Create a `.env` file inside `website/`. +2. Configure it to point to your database. +3. Read `lookup_tables` from `database.toml` if it exists. +4. Set the primary table and coordinate column names. + +## Step 3: Install Dependencies and Start the Server + +```bash +cd website/ +uv sync +uv run serve +``` + +Alternatively, you can run it manually with: +```bash +uv run uvicorn astro_web.main:app --reload --port 8000 +``` + +## Step 4: Report Success + +Inform the user that the website is running at **http://localhost:8000**. +Remind them they can stop the server with `Ctrl+C`. + +## Troubleshooting + +- **Database not found**: Ensure the `--db-path` provided to `setup_website.py` is correct. +- **Port already in use**: If 8000 is taken, use `--port ` with uvicorn. +- **Import errors**: Ensure `uv sync` was run in the `Astro-Web` directory. diff --git a/.claude/skills/astrodb-website/scripts/setup_website.py b/.claude/skills/astrodb-website/scripts/setup_website.py new file mode 100755 index 0000000..4bf0e3e --- /dev/null +++ b/.claude/skills/astrodb-website/scripts/setup_website.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +"""Setup script for Astro-Web skill. + +Generates a .env file for Astro-Web based on a provided database path. +""" + +import argparse +import sys +from pathlib import Path + +import tomllib + + +def main(): + parser = argparse.ArgumentParser(description="Setup Astro-Web .env file") + parser.add_argument("--db-path", required=True, help="Path to the SQLite database") + parser.add_argument("--website-dir", required=True, help="Directory where Astro-Web is cloned") + parser.add_argument("--toml-path", help="Path to database.toml (optional)") + parser.add_argument("--ra-col", default="ra", help="Name of the RA column (default: ra)") + parser.add_argument("--dec-col", default="dec", help="Name of the Dec column (default: dec)") + parser.add_argument("--primary-table", default="Sources", help="Name of the primary sources table (default: Sources)") + args = parser.parse_args() + + db_path = Path(args.db_path).resolve() + if not db_path.exists(): + print(f"ERROR: Database file not found: {db_path}", file=sys.stderr) + sys.exit(1) + + astro_web_dir = Path(args.website_dir).resolve() + if not astro_web_dir.exists(): + print(f"ERROR: Website directory not found at {astro_web_dir}", file=sys.stderr) + sys.exit(1) + + # Look for database.toml + toml_path = None + if args.toml_path: + toml_path = Path(args.toml_path).resolve() + else: + # Check project root (2 levels up from skills/astrodb-website/) + root_toml = Path(__file__).parent.parent.parent.parent / "database.toml" + if root_toml.exists(): + toml_path = root_toml + else: + # Check same dir as DB + db_dir_toml = db_path.parent / "database.toml" + if db_dir_toml.exists(): + toml_path = db_dir_toml + + lookup_tables = [] + if toml_path and toml_path.exists(): + print(f"Reading configuration from {toml_path}") + if tomllib: + try: + with open(toml_path, "rb") as f: + config = tomllib.load(f) + lookup_tables = config.get("lookup_tables", []) + except Exception as e: + print(f"WARNING: Could not parse {toml_path}: {e}") + else: + print("WARNING: tomllib not available, skipping database.toml parsing") + + # Prepare .env content + # Use absolute path for database URL to avoid relative path confusion + db_url = f"sqlite:///{db_path}" + + env_content = [ + f'ASTRO_WEB_DATABASE_URL="{db_url}"', + 'ASTRO_WEB_SCHEMA=""', + ] + + if lookup_tables: + env_content.append(f'ASTRO_WEB_LOOKUP_TABLES="{",".join(lookup_tables)}"') + else: + # Default lookup tables from Astro-Web .env.example + env_content.append( + 'ASTRO_WEB_LOOKUP_TABLES="Publications,Telescopes,Instruments,PhotometryFilters,Versions,RegimeList,SourceTypeList,ParameterList,AssociationList,CompanionList,Modes,Filters,Citations,References,Parameters,Regimes"' + ) + + # Add other defaults + env_content.extend( + [ + f'ASTRO_WEB_PRIMARY_TABLE="{args.primary_table}"', + 'ASTRO_WEB_SOURCE_COLUMN="source"', + 'ASTRO_WEB_FOREIGN_KEY="source"', + 'ASTRO_WEB_PRIMARY_DATATYPE="str"', + f'ASTRO_WEB_RA_COLUMN="{args.ra_col}"', + f'ASTRO_WEB_DEC_COLUMN="{args.dec_col}"', + 'ASTRO_WEB_SPECTRA_URL_COLUMN="access_url"', + 'ASTRO_WEB_SOURCE_URL_BASE="/source/"', + ] + ) + + env_path = astro_web_dir / ".env" + with open(env_path, "w") as f: + f.write("\n".join(env_content) + "\n") + + print(f"Successfully generated {env_path}") + print("\nNext steps:") + print(f" cd {astro_web_dir.relative_to(Path.cwd())}") + print(" uv sync") + print(" uv run serve # Recommended") + print(" # OR: uv run uvicorn astro_web.main:app --reload --port 8000") + + +if __name__ == "__main__": + main() diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29