{"id":15432913,"url":"https://github.com/simonw/datasette-lite","last_synced_at":"2025-05-16T07:03:26.737Z","repository":{"id":37248390,"uuid":"487877438","full_name":"simonw/datasette-lite","owner":"simonw","description":"Datasette running in your browser using WebAssembly and Pyodide","archived":false,"fork":false,"pushed_at":"2025-02-17T17:47:38.000Z","size":112,"stargazers_count":357,"open_issues_count":27,"forks_count":31,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-08T16:07:27.399Z","etag":null,"topics":["datasette","pyodide","webassembly"],"latest_commit_sha":null,"homepage":"https://lite.datasette.io","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simonw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"simonw"}},"created_at":"2022-05-02T14:34:06.000Z","updated_at":"2025-04-05T01:22:24.000Z","dependencies_parsed_at":"2024-02-01T18:59:51.764Z","dependency_job_id":"b1281d12-1680-4973-b50b-b9a763b6ffd3","html_url":"https://github.com/simonw/datasette-lite","commit_stats":{"total_commits":95,"total_committers":4,"mean_commits":23.75,"dds":0.03157894736842104,"last_synced_commit":"d547005808933198ac02bccd7492cc839f68c539"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonw%2Fdatasette-lite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonw%2Fdatasette-lite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonw%2Fdatasette-lite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonw%2Fdatasette-lite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonw","download_url":"https://codeload.github.com/simonw/datasette-lite/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254485029,"owners_count":22078767,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["datasette","pyodide","webassembly"],"created_at":"2024-10-01T18:29:15.149Z","updated_at":"2025-05-16T07:03:26.687Z","avatar_url":"https://github.com/simonw.png","language":"CSS","funding_links":["https://github.com/sponsors/simonw"],"categories":[],"sub_categories":[],"readme":"# Datasette Lite\n\nDatasette running in your browser using WebAssembly and [Pyodide](https://pyodide.org)\n\nLive tool: https://lite.datasette.io/\n\nMore about this project:\n\n- [Datasette Lite: a server-side Python web application running in a browser](https://simonwillison.net/2022/May/4/datasette-lite/)\n- [Joining CSV files in your browser using Datasette Lite](https://simonwillison.net/2022/Jun/20/datasette-lite-csvs/)\n- [Plugin support for Datasette Lite](https://simonwillison.net/2022/Aug/17/datasette-lite-plugins/)\n\n## How this works\n\nDatasette Lite runs the full server-side Datasette Python web application directly in your browser, using the [Pyodide](https://pyodide.org) build of Python compiled to WebAssembly.\n\nWhen you launch the demo, your browser will download and start executing a full Python interpreter, install the [datasette](https://pypi.org/project/datasette/) package (and its dependencies), download one or more SQLite database files and start the application running in a browser window (actually a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) attached to that window).\n\n## Load a different Datasette version\n\nDatasette Lite uses the most recent stable Datasette release [from PyPI](https://pypi.org/project/datasette/).\n\nTo use the most recent preview version (alpha or beta) add `?ref=pre`:\n\n- https://lite.datasette.io/?ref=pre\n\nOr for a specific release pass the version number as `?ref=`:\n\n- https://lite.datasette.io/?ref=0.64.2\n- https://lite.datasette.io/?ref=1.0a11\n\n## Loading CSV data\n\nYou can load data from a CSV file hosted online (provided it allows `access-control-allow-origin: *`) by passing that URL as a `?csv=` parameter - or by clicking the \"Load CSV by URL\" button and pasting in a URL.\n\nThis example loads a CSV of college fight songs from the [fivethirtyeight/data](https://github.com/fivethirtyeight/data/blob/master/fight-songs/README.md) GitHub repository:\n\n- https://lite.datasette.io/?csv=https%3A%2F%2Fraw.githubusercontent.com%2Ffivethirtyeight%2Fdata%2Fmaster%2Ffight-songs%2Ffight-songs.csv\n\nYou can pass `?csv=` multiple times to load more than one CSV file. You can then execute SQL joins to combine that data.\n\nThis example loads [the latest Covid-19 per-county data](https://github.com/nytimes/covid-19-data) from the NY Times, the 2019 county populations data from the US Census, joins them on FIPS code and runs a query that calculates cases per million across that data:\n\n[https://lite.datasette.io/?csv=https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties-recent.csv\u0026csv=https://raw.githubusercontent.com/simonw/covid-19-datasette/main/us_census_county_populations_2019.csv#/data?sql=select%0A++%5Bus-counties-recent%5D.*%2C%0A++us_census_county_populations_2019.population%2C%0A++1.0+*+%5Bus-counties-recent%5D.cases+%2F+us_census_county_populations_2019.population+*+1000000+as+cases_per_million%0Afrom%0A++%5Bus-counties-recent%5D%0A++join+us_census_county_populations_2019+on+us_census_county_populations_2019.fips+%3D+%5Bus-counties-recent%5D.fips%0Awhere%0A++population+%3E+10000%0Aorder+by%0A++cases_per_million+desc\n](https://lite.datasette.io/?csv=https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties-recent.csv\u0026csv=https://raw.githubusercontent.com/simonw/covid-19-datasette/main/us_census_county_populations_2019.csv#/data?sql=select%0A++%5Bus-counties-recent%5D.*%2C%0A++us_census_county_populations_2019.population%2C%0A++1.0+*+%5Bus-counties-recent%5D.cases+%2F+us_census_county_populations_2019.population+*+1000000+as+cases_per_million%0Afrom%0A++%5Bus-counties-recent%5D%0A++join+us_census_county_populations_2019+on+us_census_county_populations_2019.fips+%3D+%5Bus-counties-recent%5D.fips%0Awhere%0A++date+%3D+%28select+max%28date%29+from+%5Bus-counties-recent%5D%29%0Aorder+by%0A++cases_per_million+desc)\n\n## Loading JSON data\n\nIf you have data in a JSON file that looks something like this you can load it directly into Datasette Lite using the `?json=URL` parameter:\n\n```json\n[\n  {\n    \"id\": 1,\n    \"name\": \"Item 1\"\n  },\n  {\n    \"id\": 2,\n    \"name\": \"Item 2\"\n  }\n]\n```\nThis also works with JSON documents where one of the keys is a list of objects, such as this one:\n```json\n{\n  \"rows\": [\n    {\n      \"id\": 1,\n      \"name\": \"Item 1\"\n    },\n    {\n      \"id\": 2,\n      \"name\": \"Item 2\"\n    }\n  ]\n}\n```\nIn this case it will search for the first key that contains a list of objects.\n\nIf a document is a JSON object where every value is a JSON object, like this:\n\n```json\n{\n  \"anchor-positioning\": {\n    \"spec\": \"https://drafts.csswg.org/css-anchor-position-1/#anchoring\"\n  },\n  \"array-at\": {\n    \"spec\": \"https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.at\"\n  },\n  \"array-flat\": {\n    \"caniuse\": \"array-flat\",\n    \"spec\": \"https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.flat\"\n  }\n}\n```\nEach of those objects will be loaded as a separate row, with a `_key` primary key column containing the object key.\n\n[This example loads scraped data](https://lite.datasette.io/?json=https://github.com/simonw/scrape-san-mateo-fire-dispatch/blob/main/incidents.json#/data/incidents) from [this repo](https://github.com/simonw/scrape-san-mateo-fire-dispatch).\n\nNewline-delimited JSON works too - for example a file that looks like this:\n\n```\n{\"id\": 1, \"name\": \"Item 1\"}\n{\"id\": 2, \"name\": \"Item 2\"}\n```\n\n## Loading SQLite databases\n\nYou can use this tool to open any SQLite database file that is hosted online and served with a `access-control-allow-origin: *` CORS header. Files served by GitHub Pages automatically include this header, as do database files that have been published online [using datasette publish](https://docs.datasette.io/en/stable/publish.html).\n\nCopy the URL to the `.db` file and either paste it into the \"Load SQLite DB by URL\" prompt, or construct a URL like the following:\n\n    https://lite.datasette.io/?url=https://latest.datasette.io/fixtures.db\n\nSome examples to try out:\n\n- [Global Power Plants](https://lite.datasette.io/?url=https://global-power-plants.datasettes.com/global-power-plants.db) - 33,000 power plants around the world\n- [United States members of congress](https://lite.datasette.io/?url=https://congress-legislators.datasettes.com/legislators.db) - the example database from the [Learn SQL with Datasette](https://datasette.io/tutorials/learn-sql) tutorial\n\n## Loading Parquet\n\nTo load a Parquet file, pass a URL to `?parquet=`.\n\nFor example this file:\n\nhttps://github.com/Teradata/kylo/blob/master/samples/sample-data/parquet/userdata1.parquet\n\nCan be loaded like this:\n\nhttps://lite.datasette.io/?parquet=https://github.com/Teradata/kylo/blob/master/samples/sample-data/parquet/userdata1.parquet\n\n## Initializing with SQL\n\nYou can also initialize the `data.db` database by passing the URL to a SQL file. The easiest way to do this is to create a [GitHub Gist](https://gist.github.com/).\n\nThis [example SQL file](https://gist.githubusercontent.com/simonw/ac4e19920b4b360752ac0f3ce85ba238/raw/90d31cf93bf1d97bb496de78559798f849b17e85/demo.sql) creates a table and populates it with three records. It's hosted in [this Gist](https://gist.github.com/simonw/ac4e19920b4b360752ac0f3ce85ba238).\n\n    https://gist.githubusercontent.com/simonw/ac4e19920b4b360752ac0f3ce85ba238/raw/90d31cf93bf1d97bb496de78559798f849b17e85/demo.sql\n\nYou can paste this URL into the \"Load SQL by URL\" prompt, or you can pass it as the `?sql=` parameter [like this](https://lite.datasette.io/?sql=https%3A%2F%2Fgist.githubusercontent.com%2Fsimonw%2Fac4e19920b4b360752ac0f3ce85ba238%2Fraw%2F90d31cf93bf1d97bb496de78559798f849b17e85%2Fdemo.sql).\n\nSQL will be executed before any CSV imports, so you can use initial SQL to create a table and then use `?csv=` to import data into it.\n\n## Starting with just an in-memory database\n\nTo skip loading the default databases and just provide `/_memory` - useful for demonstrating plugins - pass `?memory=1`, for example:\n\nhttps://lite.datasette.io/?memory=1\n\n## Loading metadata\n\nDatasette [supports metadata](https://docs.datasette.io/en/stable/metadata.html), as a `metadata.json` or `metadata.yml` file.\n\nYou can load a metadata file in either of these formats by passing a URL to the `?metadata=` query string option.\n\n## Special handling of GitHub URLs\n\nA tricky thing about using Datasette Lite is that the files you load via URL need to be hosted somewhere that serves open CORS headers.\n\nBoth regular GitHub and [GitHub Gists](https://gist.github.com/) do this by default. This makes them excellent options to host data files that you want to load into Datasette Lite.\n\nYou can paste in the \"raw\" URL to a file, but Datasette Lite also has a shortcut: if you paste in the URL to a page on GitHub or a Gist it will automatically convert it to the \"raw\" URL for you.\n\nTry the following to see this in action:\n\n- https://lite.datasette.io/?json=https://gist.github.com/simonw/7eacc70cd8b2868be0a18796cec078b9 ([this Gist](https://gist.github.com/simonw/7eacc70cd8b2868be0a18796cec078b9))\n- https://lite.datasette.io/?csv=https://github.com/nytimes/covid-19-data/blob/master/us-counties-recent.csv ([this file](https://github.com/nytimes/covid-19-data/blob/master/us-counties-recent.csv))\n\n## Installing plugins\n\nDatasette has a number of [plugins](https://datasette.io/plugins) that enable new features.\n\nYou can install plugins into Datasette Lite by adding one or more `?install=name-of-plugin` parameters to the URL.\n\nNot all plugins are compatible with Datasette Lite at the moment, for example plugins that load their own JavaScript and CSS do not currently work, see [issue #8](https://github.com/simonw/datasette-lite/issues/8).\n\nHere's a list of plugins that have been tested with Datasette Lite, plus demo links to see them in action:\n\n- [datasette-packages](https://datasette.io/plugins/datasette-packages) - Show a list of currently installed Python packages - [demo](https://lite.datasette.io/?install=datasette-packages#/-/packages)\n- [datasette-dateutil](https://datasette.io/plugins/datasette-dateutil) - dateutil functions for Datasette - [demo](https://lite.datasette.io/?install=datasette-dateutil#/fixtures?sql=select%0A++dateutil_parse%28%2210+october+2020+3pm%22%29%2C%0A++dateutil_parse_fuzzy%28%22This+is+due+10+september%22%29%2C%0A++dateutil_parse%28%221%2F2%2F2020%22%29%2C%0A++dateutil_parse%28%222020-03-04%22%29%2C%0A++dateutil_parse_dayfirst%28%222020-03-04%22%29%3B)\n- [datasette-schema-versions](https://datasette.io/plugins/datasette-schema-versions) - Datasette plugin that shows the schema version of every attached database - [demo](https://lite.datasette.io/?install=datasette-schema-versions#/-/schema-versions)\n- [datasette-debug-asgi](https://datasette.io/plugins/datasette-debug-asgi) - Datasette plugin for dumping out the ASGI scope. - [demo](https://lite.datasette.io/?install=datasette-debug-asgi#/-/asgi-scope)\n- [datasette-query-links](https://datasette.io/plugins/datasette-query-links) - Turn SELECT queries returned by a query into links to execute them - [demo](https://lite.datasette.io/?install=datasette-query-links#/fixtures?sql=select%0D%0A++'select+*+from+[facetable]'+as+query%0D%0Aunion%0D%0Aselect%0D%0A++'select+sqlite_version()'%0D%0Aunion%0D%0Aselect%0D%0A++'select+this+is+invalid+SQL+so+will+not+be+linked')\n- [datasette-json-html](https://datasette.io/plugins/datasette-json-html) - Datasette plugin for rendering HTML based on JSON values - [demo](https://lite.datasette.io/?install=datasette-json-html#/fixtures?sql=select+%27%5B%0A++++%7B%0A++++++++%22href%22%3A+%22https%3A%2F%2Fsimonwillison.net%2F%22%2C%0A++++++++%22label%22%3A+%22Simon+Willison%22%0A++++%7D%2C%0A++++%7B%0A++++++++%22href%22%3A+%22https%3A%2F%2Fgithub.com%2Fsimonw%2Fdatasette%22%2C%0A++++++++%22label%22%3A+%22Datasette%22%0A++++%7D%0A%5D%27+as+output)\n- [datasette-haversine](https://datasette.io/plugins/datasette-haversine) - Datasette plugin that adds a custom SQL function for haversine distances - [demo](https://lite.datasette.io/?install=datasette-haversine#/fixtures?sql=select+haversine%280%2C+154%2C+1%2C+131%29)\n- [datasette-jellyfish](https://datasette.io/plugins/datasette-jellyfish) - Datasette plugin that adds custom SQL functions for fuzzy string matching, built on top of the Jellyfish Python library - [demo](https://lite.datasette.io/?install=datasette-jellyfish#/fixtures?sql=SELECT%0A++++levenshtein_distance%28%3As1%2C+%3As2%29%2C%0A++++damerau_levenshtein_distance%28%3As1%2C+%3As2%29%2C%0A++++hamming_distance%28%3As1%2C+%3As2%29%2C%0A++++jaro_similarity%28%3As1%2C+%3As2%29%2C%0A++++jaro_winkler_similarity%28%3As1%2C+%3As2%29%2C%0A++++match_rating_comparison%28%3As1%2C+%3As2%29%3B\u0026s1=barrack+obama\u0026s2=barrack+h+obama)\n- [datasette-pretty-json](https://datasette.io/plugins/datasette-pretty-json) - Datasette plugin that pretty-prints any column values that are valid JSON objects or arrays. - [demo](https://lite.datasette.io/?install=datasette-pretty-json#/fixtures?sql=select+%27%7B%22this%22%3A+%5B%22is%22%2C+%22nested%22%2C+%22json%22%5D%7D%27)\n- [datasette-yaml](https://datasette.io/plugins/datasette-yaml) - Export Datasette records as YAML - [demo](https://lite.datasette.io/?install=datasette-yaml#/fixtures/compound_three_primary_keys.yaml)\n- [datasette-copyable](https://datasette.io/plugins/datasette-copyable) - Datasette plugin for outputting tables in formats suitable for copy and paste - [demo](https://lite.datasette.io/?install=datasette-copyable#/fixtures/compound_three_primary_keys.copyable?_table_format=github)\n- [datasette-mp3-audio](https://datasette.io/plugins/datasette-mp3-audio) - Turn `.mp3` URLs into an audio player in the Datasette interface - [demo](https://lite.datasette.io/?install=datasette-mp3-audio\u0026csv=https://gist.githubusercontent.com/simonw/0a30d52feeb3ff60f7d8636b0bde296b/raw/c078a9e5a0151331e2e46c04c1ebe7edc9f45e8c/scotrail-announcements.csv#/data/scotrail-announcements)\n- [datasette-multiline-links](https://datasette.io/plugins/datasette-multiline-links) - Make multiple newline separated URLs clickable in Datasette - [demo](https://lite.datasette.io/?install=datasette-multiline-links\u0026csv=https://docs.google.com/spreadsheets/d/1wZhPLMCHKJvwOkP4juclhjFgqIY8fQFMemwKL2c64vk/export?format=csv#/data?sql=select+edition%2C+headline%2C+text%2C+links%2C+hattips+from+export+where%0Atext+like+'%25'+||+%3Aq+||+'%25'+or+headline+like+'%25'+||+%3Aq+||+'%25'+order+by+edition+desc\u0026q=loans)\n- [datasette-copyable](https://datasette.io/plugins/datasette-copyable) - adds an interface for copying out data in CSV, TSV, LaTeX, GitHub Markdown tables and many other formats - [demo](https://lite.datasette.io/?install=datasette-copyable#/content/pypi_releases.copyable?_labels=on\u0026_table_format=github)\n- [datasette-statistics](https://datasette.io/plugins/datasette-statistics) - SQL functions for statistical calculations - [demo](https://lite.datasette.io/?install=datasette-statistics#/fixtures?sql=with+numbers+as+%28%0A++++select+1+as+number%0A++++union+all%0A++++select+2%0A++++union+all%0A++++select+3%0A++++union+all%0A++++select+4%0A++++union+all%0A++++select+5%0A%29%0Aselect%0A++statistics_mean%28number%29+as+mean%2C%0A++statistics_median%28number%29+as+median%2C%0A++statistics_stdev%28number%29+as+stdev%0Afrom+numbers%3B)\n- [datasette-simple-html](https://datasette.io/plugins/datasette-simple-html) - simple SQL functions for stripping tags and escaping or unescaping HTML strings - [demo](https://lite.datasette.io/?install=datasette-simple-html#/fixtures?sql=select%0A++html_strip_tags%28%27%3Ch1%3EThis+will+have+%3Cem%3Etags+stripped%3C%2Fem%3E%3C%2Fh1%3E%27%29+as+stripped%2C%0A++html_escape%28%27%3Ch1%3EThis+will+have+%3Cem%3Etags+escaped%3C%2Fem%3E%3C%2Fh1%3E%27%29+as+escaped%2C%0A++html_unescape%28%27%26lt%3Bh1%26gt%3BThis+will+have+%26lt%3Bem%26gt%3Btags+unescaped%26lt%3B%2Fem%26gt%3B%26lt%3B%2Fh1%26gt%3B%27%29+as+unescaped)\n\n## Analytics\n\nBy default, hits to `https://lite.datasette.io/` are logged using [Plausible](https://plausible.io/).\n\nPlausible is a [privacy-focused](https://plausible.io/privacy-focused-web-analytics), cookie-free, GDPR-compliant analytics system.\n\nEach navigation within Datasette Lite is logged as a separate event to Plausible, capturing the fragment hash and the URL to the currently loaded file.\n\nThe site is hosted on GitHub Pages, which does not offer any analytics that are visible to the site owner. GitHub Pages can only log visits to the `https://lite.datasette.io/` root page - it will not have visibility into any subsequent `#` fragment navigation.\n\nTo opt out of analytics, you can add `?analytics=off` or `\u0026analytics=off` to the URL. This will prevent any analytics being sent to Plausible.\n\n## Running the tests\n\nRun the tests by running `pytest` after first installing the `dev-requirements.txt` dependencies.\n\nTo do that using `uv` first run `playwright install` to download the Playwright browsers:\n\n```bash\nuv run --python 3.10 \\\n  --with-requirements dev-requirements.txt \\\n  python -m playwright install\n```\nThen run `pytest` like this:\n```bash\nuv run --python 3.10 \\\n  --with-requirements dev-requirements.txt \\\n  python -m pytest\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonw%2Fdatasette-lite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonw%2Fdatasette-lite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonw%2Fdatasette-lite/lists"}