[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-10406":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":23,"hasPages":23,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":29,"readmeContent":30,"aiSummary":31,"trendingCount":16,"starSnapshotCount":16,"syncStatus":32,"lastSyncTime":33,"discoverSource":34},10406,"grist-core","gristlabs\u002Fgrist-core","gristlabs","Grist is the evolution of spreadsheets.","https:\u002F\u002Fwww.getgrist.com",null,"TypeScript",11129,583,69,605,0,4,18,94,17,94.7,"Apache License 2.0",false,"main",[26,27,28],"awesome","database","spreadsheet","2026-06-12 04:00:50","# Grist\n\nGrist is a modern relational spreadsheet. It combines the flexibility of a spreadsheet with the robustness of a database.\n\n* `grist-core` (this repo – also known as Grist Community edition) has what you need to run a powerful server for hosting spreadsheets.\n* [`grist-desktop`](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-desktop) is a Linux\u002FmacOS\u002FWindows desktop app for viewing and editing spreadsheets stored locally.\n* [`grist-static`](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-static) is a fully in-browser build of Grist for displaying spreadsheets on a website without back-end support.\n\nGrist is developed by [Grist Labs](https:\u002F\u002Fwww.linkedin.com\u002Fcompany\u002Fgrist-labs\u002F), an NYC-based company 🇺🇸🗽. The French government 🇫🇷 organizations [ANCT Données et Territoires](https:\u002F\u002Fdonnees.incubateur.anct.gouv.fr\u002Ftoolbox\u002Fgrist) and [DINUM (Direction Interministérielle du Numérique)](https:\u002F\u002Fwww.numerique.gouv.fr\u002Fdinum\u002F) have also made significant contributions to the codebase.\n\nThe `grist-core`, `grist-desktop`, and `grist-static` repositories are all open-source (Apache License, Version 2.0). Grist Labs sells an edition of Grist with [additional features](#features-not-in-grist-core). Grist Labs also offers free and paid hosted services at [getgrist.com](https:\u002F\u002Fgetgrist.com),\nas well as [cloud packaging](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Fgrist-builder-edition\u002F).\n\n> Questions? Feedback? Want to share what you're building with Grist? Join our [official Discord server](https:\u002F\u002Fdiscord.gg\u002FMYKpYQ3fbP) or visit our [Community forum](https:\u002F\u002Fcommunity.getgrist.com\u002F). \n>\n> To keep up-to-date with everything that's going on, you can [sign up for Grist's monthly newsletter](https:\u002F\u002Fwww.getgrist.com\u002Fnewsletter\u002F).\n\nhttps:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Ffe152f60-3d15-4b11-8cb2-05731a90d273\n\n## Features in `grist-core`\n\nTo see exactly what is present in `grist-core`, you can run the [desktop app](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-desktop), or use [`docker`](#using-grist). The absolute fastest way to try Grist out is to visit [docs.getgrist.com](https:\u002F\u002Fdocs.getgrist.com) and play with a spreadsheet there immediately – though if you do, please read the list of [additional features](#features-not-in-grist-core) that are not in `grist-core`.\n\nHowever you try it, you'll quickly see that Grist is a hybrid database\u002Fspreadsheet, meaning that:\n\n  - Columns work like they do in databases: they are named, and they hold one kind of data.\n  - Columns can be filled by formula, spreadsheet-style, with automatic updates when referenced cells change.\n\nThis difference can confuse people coming directly from Excel or Google Sheets. Give it a chance! There's also a [Grist for Spreadsheet Users](https:\u002F\u002Fwww.getgrist.com\u002Fblog\u002Fgrist-for-spreadsheet-users\u002F) article to help get you oriented. If you're coming from Airtable, you'll find the model familiar (and there's also our [Grist vs Airtable](https:\u002F\u002Fwww.getgrist.com\u002Fblog\u002Fgrist-v-airtable\u002F) article for a direct comparison).\n\nHere are some specific feature highlights of Grist (🇫🇷 marks heavy French govt. contributions):\n\n  * Python formulas.\n    - Full [Python syntax is supported](https:\u002F\u002Fsupport.getgrist.com\u002Fformulas\u002F#python), including the standard library.\n    - Many [Excel functions](https:\u002F\u002Fsupport.getgrist.com\u002Ffunctions\u002F) also available.\n    - An [AI Formula Assistant](https:\u002F\u002Fsupport.getgrist.com\u002Fai-assistant-legacy\u002F) specifically tuned for formula generation (works with OpenAI, [Llama](https:\u002F\u002Fai.meta.com\u002Fllama\u002F), and many other models via [OpenRouter](https:\u002F\u002Fopenrouter.ai\u002F) or any OpenAI-compatible endpoint).\n    - A [formula timer](https:\u002F\u002Fsupport.getgrist.com\u002Fformula-timer\u002F) for diagnosing slow formulas.\n  * A portable, self-contained format.\n    - Based on SQLite, the most widely deployed database engine.\n    - Any tool that can read SQLite can read numeric and text data from a Grist file.\n    - Enables [backups](https:\u002F\u002Fsupport.getgrist.com\u002Fexports\u002F#backing-up-an-entire-document) that you can confidently restore in full.\n    - Great for moving between different hosts.\n  * Can be displayed on a static website with [`grist-static`](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-static) – no special server needed.\n  * A self-contained desktop app for viewing and editing locally: [`grist-desktop`](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-desktop).\n  * Convenient editing and formatting features.\n    - Choices and [choice lists](https:\u002F\u002Fsupport.getgrist.com\u002Fcol-types\u002F#choice-list-columns), for adding colorful tags to records.\n    - [References](https:\u002F\u002Fsupport.getgrist.com\u002Fcol-refs\u002F#creating-a-new-reference-list-column) and reference lists, for cross-referencing records in other tables.\n    - [Two-way references](https:\u002F\u002Fsupport.getgrist.com\u002Fcol-refs\u002F#two-way-references) that automatically synchronize between tables.\n    - [Attachments](https:\u002F\u002Fsupport.getgrist.com\u002Fcol-types\u002F#attachment-columns), to include media or document files in records.\n    - Dates and times, toggles, and special numerics such as currency all have specialized editors and formatting options.\n    - [Conditional Formatting](https:\u002F\u002Fsupport.getgrist.com\u002Fconditional-formatting\u002F), letting you control the style of cells with formulas to draw attention to important information.\n    - [Markdown formatting](https:\u002F\u002Fsupport.getgrist.com\u002Fcol-types\u002F#markdown) in text cells.\n  * Drag-and-drop dashboards.\n    - [Charts](https:\u002F\u002Fsupport.getgrist.com\u002Fwidget-chart\u002F), [card views](https:\u002F\u002Fsupport.getgrist.com\u002Fwidget-card\u002F) and a [calendar widget](https:\u002F\u002Fsupport.getgrist.com\u002Fwidget-calendar\u002F) for visualization.\n    - [Summary tables](https:\u002F\u002Fsupport.getgrist.com\u002Fsummary-tables\u002F) for summing and counting across groups.\n    - [Widget linking](https:\u002F\u002Fsupport.getgrist.com\u002Flinking-widgets\u002F) streamlines filtering and editing data.\n    Grist has a unique approach to visualization, where you can lay out and link distinct widgets to show together,\n    without cramming mixed material into a table.\n    - [Filter bar](https:\u002F\u002Fsupport.getgrist.com\u002Fsearch-sort-filter\u002F#pinning-filters) for quick slicing and dicing.\n    - Duplicate widgets to quickly build variations of a view.\n    - [Compare documents](https:\u002F\u002Fsupport.getgrist.com\u002Fcopying-docs\u002F#trying-out-changes) to see what changed.\n  * [Incremental imports](https:\u002F\u002Fsupport.getgrist.com\u002Fimports\u002F#updating-existing-records).\n    - Import a CSV of the last three months activity from your bank...\n    - ...and import new activity a month later without fuss or duplication.\n  * [Native forms](https:\u002F\u002Fsupport.getgrist.com\u002Fwidget-form\u002F). Create forms that feed directly into your spreadsheet without fuss.\n    - Supports file attachments, hidden fields, and pre-population via URL parameters.\n  * Integrations.\n    - A [REST API](https:\u002F\u002Fsupport.getgrist.com\u002Fapi\u002F) with an interactive [API console](https:\u002F\u002Fdocs.getgrist.com\u002Fapiconsole), [Zapier actions\u002Ftriggers](https:\u002F\u002Fzapier.com\u002Fapps\u002Fgrist\u002Fintegrations), and support from similar [integrators](https:\u002F\u002Fsupport.getgrist.com\u002Fintegrators\u002F).\n    - Import\u002Fexport to Google Drive, Excel format, CSV. [Import directly from Airtable.](https:\u002F\u002Fsupport.getgrist.com\u002Fimports\u002F#import-from-airtable)\n    - Link data with [custom widgets](https:\u002F\u002Fsupport.getgrist.com\u002Fwidget-custom\u002F), hosted externally.\n    - Configurable outgoing [webhooks](https:\u002F\u002Fsupport.getgrist.com\u002Fwebhooks\u002F), with support for authorization headers, column-specific triggers, and formula conditions.\n    - [Service accounts](https:\u002F\u002Fsupport.getgrist.com\u002Fapi\u002F#tag\u002Fservice-accounts) for fine-tuned API access (🇫🇷).\n    - [SCIM](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Fscim\u002F) for standard user and group provisioning (🇫🇷).\n  * [Many templates](https:\u002F\u002Ftemplates.getgrist.com\u002F) to get you started, from investment research to organizing treasure hunts.\n  * Access control options.\n    - (You'll need SSO logins set up to make use of these options; [`grist-omnibus`](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-omnibus) has a prepackaged solution if configuring this feels daunting)\n    - Share [individual documents](https:\u002F\u002Fsupport.getgrist.com\u002Fsharing\u002F), workspaces, or [team sites](https:\u002F\u002Fsupport.getgrist.com\u002Fteam-sharing\u002F).\n    - Control access to [individual rows, columns, and tables](https:\u002F\u002Fsupport.getgrist.com\u002Faccess-rules\u002F).\n    - Control access based on cell values and user attributes.\n    - [OIDC](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Foidc\u002F) (🇫🇷) and [SAML](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Fsaml\u002F) support for single sign-on.\n  * Collaboration.\n    - [Comments](https:\u002F\u002Fsupport.getgrist.com\u002Fsharing\u002F#comments) on cells, with threaded replies and @-mentions.\n    - See who else is viewing a document in real time.\n    - [Suggest changes](https:\u002F\u002Fsupport.getgrist.com\u002Fsharing\u002F#suggestions) for others to review and approve, inspired by source control workflows.\n  * Self-maintainable.\n    - Useful for intranet operation and specific compliance requirements.\n    - [Sign in with getgrist.com](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Fsign-in-with-grist\u002F) for easy authentication without running your own auth server.\n    - Store [attachments externally](https:\u002F\u002Fsupport.getgrist.com\u002Fdocument-settings\u002F#external-attachments) in S3-compatible storage to keep `.grist` files small (🇫🇷).\n    - [HTTP long polling](https:\u002F\u002Fsupport.getgrist.com\u002Fnewsletters\u002F2024-04\u002F#networking-improvements) as an alternative to WebSockets for restrictive network environments (🇫🇷).\n  * Sandboxing options for untrusted documents.\n    - On Linux or with Docker, you can enable [gVisor](https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgvisor) sandboxing at the individual document level.\n    - On macOS, you can use native sandboxing.\n    - On any OS, including Windows, you can use a Wasm-based sandbox via [Deno](https:\u002F\u002Fdeno.com\u002F) and [Pyodide](https:\u002F\u002Fpyodide.org\u002F).\n  * Translated to many languages (🇫🇷).\n  * A [high-contrast theme](https:\u002F\u002Fsupport.getgrist.com\u002Fnewsletters\u002F2025-05\u002F#high-contrast-theme) meeting WCAG level AA requirements (🇫🇷).\n  * `F1` key brings up some quick help. This used to go without saying, but in general Grist has good keyboard support (🇫🇷).\n  * We post progress on [𝕏 or Twitter or whatever](https:\u002F\u002Ftwitter.com\u002Fgetgrist) and publish [monthly newsletters](https:\u002F\u002Fsupport.getgrist.com\u002Fnewsletters\u002F).\n\nIf you are curious about where Grist is heading, see [our roadmap](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-core\u002Fprojects\u002F1), drop a question in [our forum](https:\u002F\u002Fcommunity.getgrist.com), or browse [our extensive documentation](https:\u002F\u002Fsupport.getgrist.com).\n\n## Features not in `grist-core`\n\nIf you evaluate Grist by using the hosted version at [getgrist.com](https:\u002F\u002Fgetgrist.com), be aware that it includes some features that aren't present in `grist-core`. To be sure you're seeing exactly what is present in `grist-core`, you can run the [desktop app](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-desktop), or use [`docker`](#using-grist).\n\nHere is a list of features available in the full edition of Grist that are not in `grist-core`, in chronological order of creation. If self-hosting, you can get access to a free trial of all of them by selecting the full edition of Grist on the [Admin Panel](https:\u002F\u002Fsupport.getgrist.com\u002Fadmin-panel\u002F). The full edition of Grist is free for individuals and small orgs with less than US $1 million in total annual funding. Learn more about that [here](https:\u002F\u002Fwww.getgrist.com\u002Ffree-grist-activation-key-faq\u002F).\n\n  * [GristConnect](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Fgrist-connect\u002F) (2022)\n    - Any site that has plugins for letting Discourse use its logins (such as WordPress) can also let Grist use its logins.\n    - GristConnect is a niche feature built for a specific client which you probably don't care about – `OIDC` and `SAML` support *is* part of `grist-core` and covers most authentication use cases.\n  * [Azure back-end for document storage](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Fcloud-storage\u002F#azure) (2022)\n    - With `grist-core` you can store document versions in anything S3-compatible, which covers a lot of services, but not Azure specifically. The Azure back-end fills that gap.\n    - Unless you are a Microsoft shop you probably don't care about this.\n  * [Audit log streaming](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Faudit-log-streaming\u002F) (2024)\n    - With `grist-core` a lot of useful information is logged, but not organized specifically with auditing in mind. Audit log streaming supplies that organization, and a UI for setting things up.\n    - Enterprises may care about this.\n  * [Advanced Admin Controls](https:\u002F\u002Fsupport.getgrist.com\u002Fadmin-controls\u002F) (2025)\n    - This is a special page for a Grist installation administrator to monitor and edit user access to resources.\n    - It uses a special set of administrative endpoints not present on `grist-core`.\n    - If you're going to be running a large Grist installation, with employees coming and going, you may care about this.\n  * [Grist Assistant](https:\u002F\u002Fsupport.getgrist.com\u002Fassistant\u002F#assistant) (2025)\n    - An AI Formula Assistant - limited to working with formulas - is present in `grist-core`, but the newer Assistant can help with a wider range of tasks like building tables and dashboards, styling and formatting, explaining access rules, and modifying data.\n    - If you have many users who need help building documents or working with data, you may care about this one.\n  * [Invite Notifications](https:\u002F\u002Fsupport.getgrist.com\u002Fself-managed\u002F#how-do-i-set-up-email-notifications) (2025)\n    - When a user is added to a document, or a workspace, or a site, with email notifications they will get emailed a link to access the resource.\n    - This link isn't special, with `grist-core` you can just send a link yourself or a colleague.\n    - For a big Grist installation with users who aren't in close communication, emails might be nice? Hard to guess if you'll care about this one.\n  * [Document Change and Comment Notifications](https:\u002F\u002Fsupport.getgrist.com\u002Fdocument-settings\u002F#notifications) (2025)\n    - You can achieve change notifications in `grist-core` using webhooks, but it is less convenient.\n    - People have been asking for this one for years. If you need an excuse to get your boss to pay for Grist, this might finally be the one that works?\n\n## Using Grist\n\nTo get the default version of `grist-core` running on your computer\nwith [Docker](https:\u002F\u002Fwww.docker.com\u002Fget-started), do:\n\n```sh\ndocker pull gristlabs\u002Fgrist\ndocker run -p 8484:8484 -it gristlabs\u002Fgrist\n```\n\nThen visit `http:\u002F\u002Flocalhost:8484` in your browser. You'll be able to create, edit, import,\nand export documents. To preserve your work across docker runs, share a directory as `\u002Fpersist`:\n\n```sh\ndocker run -p 8484:8484 -v $PWD\u002Fpersist:\u002Fpersist -it gristlabs\u002Fgrist\n```\n\nGet templates at [templates.getgrist.com](https:\u002F\u002Ftemplates.getgrist.com) for payroll,\ninventory management, invoicing, D&D encounter tracking, and a lot\nmore, or use any document you've created on\n[docs.getgrist.com](https:\u002F\u002Fdocs.getgrist.com).\n\nIf you need to change the port Grist runs on, set a `PORT` variable, don't just change the\nport mapping:\n\n```\ndocker run --env PORT=9999 -p 9999:9999 -v $PWD\u002Fpersist:\u002Fpersist -it gristlabs\u002Fgrist\n```\n\nTo enable gVisor sandboxing, set `--env GRIST_SANDBOX_FLAVOR=gvisor`.\nThis should work with default docker settings, but may not work in all\nenvironments.\n\nYou can find a lot more about configuring Grist, setting up authentication,\nand running it on a public server in our\n[Self-Managed Grist](https:\u002F\u002Fsupport.getgrist.com\u002Fself-managed\u002F) documentation.\n\n## Using Grist with OpenRouter for Model Agnostic and Claude Support\n\n(Instructions contributed by @lshalon)\n\nGrist's AI Formula Assistant can be configured to use OpenRouter instead of connecting directly to OpenAI, allowing you to access a wide range of AI models including Anthropic's Claude models. This isn't the only way to use Claude models, but it's a good option if you want to use Claude models with Grist or intend to use other cheaper, faster, or potentially newer models. That's because this configuration gives you more flexibility in choosing the AI model that works best for your formula generation needs.\nTo set up OpenRouter integration, configure the following environment variables:\n\n### Required: Set the endpoint to OpenRouter's API\n\n```\nASSISTANT_CHAT_COMPLETION_ENDPOINT=https:\u002F\u002Fopenrouter.ai\u002Fapi\u002Fv1\u002Fchat\u002Fcompletions\n```\n\n### Required: Your OpenRouter API key\n\n```\nASSISTANT_API_KEY=your_openrouter_api_key_here\n```\n\nSign up for an OpenRouter API key at \u003Chttps:\u002F\u002Fopenrouter.ai\u002F>\n\n### Optional: Specify which model to use (examples below)\n\n```\nASSISTANT_MODEL=anthropic\u002Fclaude-3.7-sonnet\n```\n\n### or other options like\n\n```\nASSISTANT_MODEL=deepseek\u002Fdeepseek-r1-zero:free\n```\n\n```\nASSISTANT_MODEL=qwen\u002Fqwq-32b:free\n```\n\n```\nASSISTANT_MODEL=mistralai\u002Fmistral-saba\n```\n\n### Optional: Set a larger context model for fallback\n\n```\nASSISTANT_LONGER_CONTEXT_MODEL=anthropic\u002Fclaude-3-opus-20240229\n```\n\nWith this configuration, Grist's AI Formula Assistant will route requests through OpenRouter to your specified model. This allows you to:\n\nAccess Anthropic's Claude models which excel at understanding context and generating accurate formulas\nSwitch between different AI models without changing your Grist configuration\nTake advantage of OpenRouter's routing capabilities to optimize for cost, speed, or quality\n\nYou can find the available models and their identifiers on the OpenRouter website.\nNote: Make sure not to set the OPENAI_API_KEY variable when using OpenRouter, as this would override the OpenRouter configuration.\n\n\n## Available Docker images\n\nThe default Docker image is `gristlabs\u002Fgrist`. This contains all of\nthe Grist Community edition features, as well as extra source-available\ncode for the full edition of Grist. This\nextra code is not under a free or open-source license, though by default is completely inert\nand inactive. This code becomes active only when enabled from the\nAdmin Panel.\n\nIf you would rather use an image that contains exclusively free and\nopen-source code, the `gristlabs\u002Fgrist-oss` Docker image is available\nfor this purpose. It is by default functionally equivalent to the\n`gristlabs\u002Fgrist` image.\n\n## The Admin Panel\n\nYou can turn on a special admininistrator panel to inspect the status\nof your installation. Just visit `\u002Fadmin` on your Grist server for\ninstructions. Since it is useful for the admin panel to be\navailable even when authentication isn't set up, you can give it a\nspecial access key by setting `GRIST_BOOT_KEY`.\n\n```\ndocker run -p 8484:8484 -e GRIST_BOOT_KEY=secret -it gristlabs\u002Fgrist\n```\n\nThe boot page should then be available at\n`\u002Fadmin?boot-key=\u003CGRIST_BOOT_KEY>`. We are collecting probes for\ncommon problems there. If you hit a problem that isn't covered, it\nwould be great if you could add a probe for it in\n[BootProbes](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-core\u002Fblob\u002Fmain\u002Fapp\u002Fserver\u002Flib\u002FBootProbes.ts).\nYou may instead file an issue so someone else can add it.\n\n## Building from source\n\nTo build Grist from source, follow these steps:\n\n    yarn install\n    yarn install:python\n    yarn build\n    yarn start\n    # Grist will be available at http:\u002F\u002Flocalhost:8484\u002F\n\nGrist formulas in documents will be run using Python executed directly on your\nmachine. You can configure sandboxing using a `GRIST_SANDBOX_FLAVOR`\nenvironment variable.\n\n * On macOS, `export GRIST_SANDBOX_FLAVOR=macSandboxExec`\n   uses the native `sandbox-exec` command for sandboxing.\n * On Linux with [gVisor's runsc](https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgvisor)\n   installed, `export GRIST_SANDBOX_FLAVOR=gvisor` is an option.\n * On any OS including Windows, `export GRIST_SANDBOX_FLAVOR=pyodide` is available.\n\nThese sandboxing methods have been written for our own use at Grist Labs and\nmay need tweaking to work in your own environment - pull requests\nvery welcome here!\n\nIf you wish to include full Grist extensions in your build, the steps are as follows. Note that this will add non-OSS code to your build. It will also place a directory called `node_modules` one level up, at the same level as the Grist repo. If that is a problem for you, just move everything into a subdirectory first.\n\n    yarn install\n    yarn install:ee\n    yarn install:python\n    yarn build\n    yarn start\n    # Grist will be available at http:\u002F\u002Flocalhost:8484\u002F\n\nYou may toggle between the full Grist and Community editions in the [Admin Panel](https:\u002F\u002Fsupport.getgrist.com\u002Fself-managed\u002F#how-do-i-enable-the-full-edition-of-grist).\n\n## Logins\n\nLike git, Grist has features to track document revision history. So for full operation,\nGrist expects to know who the user modifying a document is. Until it does, it operates\nin a limited anonymous mode. To get you going, the docker image is configured so that\nwhen you click on the \"sign in\" button Grist will attribute your work to `you@example.com`.\nChange this by setting `GRIST_DEFAULT_EMAIL`:\n\n```\ndocker run --env GRIST_DEFAULT_EMAIL=my@email -p 8484:8484 -v $PWD\u002Fpersist:\u002Fpersist -it gristlabs\u002Fgrist\n```\n\nYou can change your name in `Profile Settings` in\nthe [User Menu](https:\u002F\u002Fsupport.getgrist.com\u002Fglossary\u002F#user-menu).\n\nFor multi-user operation, or if you wish to access Grist across the\npublic internet, you'll want to connect it to your own Single Sign-On service.\nThere are a lot of ways to do this, including [SAML and forward authentication](https:\u002F\u002Fsupport.getgrist.com\u002Fself-managed\u002F#how-do-i-set-up-authentication).\nGrist has been tested with [Authentik](https:\u002F\u002Fgoauthentik.io\u002F), [Auth0](https:\u002F\u002Fauth0.com\u002F),\nand Google\u002FMicrosoft sign-ins via [Dex](https:\u002F\u002Fdexidp.io\u002F).\n\n## Translations\n\nWe use [Weblate](https:\u002F\u002Fhosted.weblate.org\u002Fengage\u002Fgrist\u002F) to manage translations.\nThanks to everyone who is pitching in. Thanks especially to the ANCT developers who\ndid the hard work of making a good chunk of the application localizable. Merci beaucoup !\n\n\u003Ca href=\"https:\u002F\u002Fhosted.weblate.org\u002Fengage\u002Fgrist\u002F\">\n\u003Cimg src=\"https:\u002F\u002Fhosted.weblate.org\u002Fwidgets\u002Fgrist\u002F-\u002Fopen-graph.png\" alt=\"Translation status\" width=480 \u002F>\n\u003C\u002Fa>\n\n[![Translation detail](https:\u002F\u002Fhosted.weblate.org\u002Fwidgets\u002Fgrist\u002F-\u002Fmulti-green.svg)](https:\u002F\u002Fhosted.weblate.org\u002Fengage\u002Fgrist\u002F)\n\n## Why free and open-source software?\n\nThis repository, `grist-core`, is maintained by Grist Labs. Our flagship product available at [getgrist.com](https:\u002F\u002Fwww.getgrist.com) is built from the code you see here, combined with business-specific software designed to scale to many users, handle billing, etc.\n\nGrist Labs is an open-core company. We offer Grist hosting as a service, with free and paid plans. We also develop and sell features related to Grist using a proprietary license, targeted at the needs of enterprises with large self-managed installations.\n\nWe see data portability and autonomy as a key value, and `grist-core` is an essential part of that. We are committed to maintaining and improving the `grist-core` codebase, and to be thoughtful about how proprietary offerings impact data portability and autonomy.\n\nBy opening its source code and offering an [OSI](https:\u002F\u002Fopensource.org\u002F)-approved free license, Grist benefits its users:\n\n- **Developer community.** The freedom to examine source code, make bug fixes, and develop\n  new features is a big deal for a general-purpose spreadsheet-like product, where there is a\n  very long tail of features vital to someone somewhere.\n- **Increased trust.** Because anyone can examine the source code, &ldquo;security by obscurity&rdquo; is not\n  an option. Vulnerabilities in the code can be found by others and reported before they cause\n  damage.\n- **Independence.** Grist is available to you regardless of the fortunes of the Grist Labs business,\n  since it is open-source and can be self-hosted. Using our hosted solution is convenient, but you\n  are not locked in.\n- **Price flexibility.** If you are low on funds but have time to invest, self-hosting is a great\n  option to have. And DIY users may have the technical savvy and motivation to delve in and make improvements,\n  which can benefit all users of Grist.\n- **Extensibility.** For developers, having the source open makes it easier to build extensions (such as [Custom Widgets](https:\u002F\u002Fsupport.getgrist.com\u002Fwidget-custom\u002F)). You can more easily include Grist in your pipeline. And if a feature is missing, you can just take the source code and build on top of it.\n\nFor more on Grist Labs' history and principles, see our [About Us](https:\u002F\u002Fwww.getgrist.com\u002Fabout\u002F) page.\n\n## Sponsors\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fwww.dotphoton.com\u002F\">\n    \u003Cimg width=\"11%\" src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F11277225\u002F228914729-ae581352-b37a-4ca8-b220-b1463dd1ade0.png\" \u002F>\n  \u003C\u002Fa>\n\u003C\u002Fp>\n\n## Reviews\n\n * [Grist on ProductHunt](https:\u002F\u002Fwww.producthunt.com\u002Fposts\u002Fgrist-2)\n * [Grist on AppSumo](https:\u002F\u002Fappsumo.com\u002Fproducts\u002Fgrist\u002F) (life-time deal is sold out)\n * [Capterra](https:\u002F\u002Fwww.capterra.com\u002Fp\u002F232821\u002FGrist\u002F#reviews), [G2](https:\u002F\u002Fwww.g2.com\u002Fproducts\u002Fgrist\u002Freviews), [TrustRadius](https:\u002F\u002Fwww.trustradius.com\u002Fproducts\u002Fgrist\u002Freviews)\n\n## Environment variables\n\nGrist can be configured in many ways. Here are the main environment variables it is sensitive to:\n\n| Variable | Purpose |\n| -------- | ------- |\n| ALLOWED_WEBHOOK_DOMAINS | comma-separated list of permitted domains to use in webhooks (e.g. webhook.site,zapier.com). You can set this to `*` to allow all domains, but if doing so, we recommend using a carefully locked-down proxy (see `GRIST_PROXY_FOR_UNTRUSTED_URLS`) if you do not entirely trust users. Otherwise services on your internal network may become vulnerable to manipulation. |\n| APP_DOC_URL | doc worker url, set when starting an individual doc worker (other servers will find doc worker urls via redis) |\n| APP_DOC_INTERNAL_URL | like `APP_DOC_URL` but used by the home server to reach the server using an internal domain name resolution (like in a docker environment). It only makes sense to define this value in the doc worker. Defaults to `APP_DOC_URL`. |\n| APP_HOME_URL | url prefix for home api (home and doc servers need this) |\n| APP_HOME_INTERNAL_URL | like `APP_HOME_URL` but used by the home and the doc servers to reach any home workers using an internal domain name resolution (like in a docker environment). Defaults to `APP_HOME_URL` |\n| APP_STATIC_URL | url prefix for static resources |\n| APP_STATIC_INCLUDE_CUSTOM_CSS | set to \"true\" to include custom.css (from APP_STATIC_URL) in static pages |\n| APP_UNTRUSTED_URL | URL at which to serve\u002Fexpect plugin content. |\n| GRIST_ACTION_HISTORY_MAX_ROWS | Maximum number of rows allowed in ActionHistory before pruning (up to a 1.25 grace factor). Defaults to 1000. ⚠️ A too low value may make the \"[Work on a copy](https:\u002F\u002Fsupport.getgrist.com\u002Fnewsletters\u002F2021-06\u002F#work-on-a-copy)\" feature [malfunction](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-core\u002Fissues\u002F1121#issuecomment-2248112023) |\n| GRIST_ACTION_HISTORY_MAX_BYTES | Maximum number of rows allowed in ActionHistory before pruning (up to a 1.25 grace factor). Defaults to 1Gb. ⚠️ A too low value may make the \"[Work on a copy](https:\u002F\u002Fsupport.getgrist.com\u002Fnewsletters\u002F2021-06\u002F#work-on-a-copy)\" feature [malfunction](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-core\u002Fissues\u002F1121#issuecomment-2248112023) |\n| GRIST_ADAPT_DOMAIN | set to \"true\" to support multiple base domains (careful, host header should be trustworthy) |\n| GRIST_ALLOW_AUTOMATIC_VERSION_CHECKING | Whether Grist is allowed to automatically check if a newer Grist version is available. Defaults to \"true\" on the default `grist` and `grist-ee` Docker images. Defaults false in `grist-oss` and everywhere else. |\n| GRIST_ALLOW_DEPRECATED_BARE_ORG_DELETE | If set, the deprecated DELETE \u002Fapi\u002Forgs\u002F:orgId endpoint is available. |\n| GRIST_APP_ROOT | directory containing Grist sandbox and assets (specifically the sandbox and static subdirectories). |\n| GRIST_ATTACHMENT_THRESHOLD_MB | attachment storage limit per document beyond which Grist will recommend external storage (if available). Defaults to 50MB. |\n| GRIST_BACKUP_DELAY_SECS | wait this long after a doc change before making a backup |\n| GRIST_BOOT_KEY | if set, enable signing in as the installation admin on \u002Fboot with this key |\n| GRIST_BROADCAST_TIMEOUT_MS | Set the maximum time a web client has to accept a broadcast message about a document before being disconnected (default: 1 minute). |\n| GRIST_DATA_DIR | Directory in which to store documents. Defaults to `docs\u002F` relative to the Grist application directory. In Grist's default Docker image, its default value is \u002Fpersist\u002Fdocs so that it will be used as a mounted volume. |\n| GRIST_DEFAULT_EMAIL | if set, login as this user if no other credentials presented |\n| GRIST_DEFAULT_PRODUCT | if set, this controls enabled features and limits of new sites. See names of PRODUCTS in Product.ts. |\n| GRIST_DEFAULT_LOCALE | Locale to use as fallback when Grist cannot honour the browser locale. |\n| GRIST_DOMAIN | in hosted Grist, Grist is served from subdomains of this domain.  Defaults to \"getgrist.com\". |\n| GRIST_EXPERIMENTAL_PLUGINS | enables experimental plugins |\n| GRIST_EXTERNAL_ATTACHMENTS_MODE | required to enable external storage for attachments. Set to \"snapshots\" to enable external storage. Default value is \"none\". Note that when enabled, a [snapshot storage has to be configured](https:\u002F\u002Fsupport.getgrist.com\u002Fself-managed\u002F#how-do-i-set-up-snapshots) as well. |\n| GRIST_ENABLE_SERVICE_ACCOUNTS | enables the `service accounts` feature. This feature allows users to create special service accounts that they can manage and to whom they can grant restricted access to chosen resources. Useful as a way to get fine-grained api keys for use with third party automations. Unset by default |\n| GRIST_ENABLE_REQUEST_FUNCTION | enables the REQUEST function. This function performs HTTP requests in a similar way to `requests.request`. This function presents a significant security risk, since it can let users call internal endpoints when Grist is available publicly. This function can also cause performance issues. Unset by default. |\n| GRIST_HEADERS_TIMEOUT_MS | if set, override nodes's server.headersTimeout flag. |\n| GRIST_HIDE_UI_ELEMENTS | comma-separated list of UI features to disable. Allowed names of parts: `helpCenter`, `billing`, `templates`, `createSite`, `multiSite`, `multiAccounts`, `importFromAirtable`, `sendToDrive`, `tutorials`, `supportGrist`, `themes`, `automations`. If a part also exists in GRIST_UI_FEATURES, it will still be disabled. |\n| GRIST_HOST | hostname to use when listening on a port. |\n| GRIST_PROXY_FOR_UNTRUSTED_URLS | Full URL of proxy for delivering webhook payloads. Default value is `direct` for delivering payloads without proxying. |\n| HTTPS_PROXY or https_proxy | Full URL of reverse web proxy (corporate proxy) for fetching the custom widgets repository or the OIDC config from the issuer. |\n| GRIST_ID_PREFIX | for subdomains of form o-*, expect or produce o-${GRIST_ID_PREFIX}*. |\n| GRIST_IGNORE_SESSION | if set, Grist will not use a session for authentication. |\n| GRIST_INCLUDE_CUSTOM_SCRIPT_URL | if set, will load the referenced URL in a `\u003Cscript>` tag on all app pages. |\n| GRIST_INST_DIR | path to Grist instance configuration files, for Grist server. |\n| GRIST_KEEP_ALIVE_TIMEOUT_MS | if set, override nodes's server.keepAliveTimeout flag. |\n| GRIST_LIST_PUBLIC_SITES | if set to true, sites shared with the public will be listed for anonymous users. Defaults to false. |\n| GRIST_MANAGED_WORKERS | if set, Grist can assume that if a url targeted at a doc worker returns a 404, that worker is gone |\n| GRIST_MAX_NEW_USER_INVITES_PER_ORG | if set, limits the number of invites to new users per org. Once exceeded, additional invites are blocked until invited users log in for the first time or are uninvited\n| GRIST_MAX_BILLING_MANAGERS_PER_ORG | if set, limits the number of billing managers per org |\n| GRIST_MAX_PARALLEL_REQUESTS_PER_DOC| max number of concurrent API requests allowed per document (default is 10, set to 0 for unlimited) |\n| GRIST_MAX_UPLOAD_ATTACHMENT_MB | max allowed size for attachments (0 or empty for unlimited). |\n| GRIST_MAX_UPLOAD_IMPORT_MB | max allowed size for imports (except .grist files) (0 or empty for unlimited). |\n| GRIST_OFFER_ALL_LANGUAGES | if set, all translated langauages are offered to the user (by default, only languages with a special 'good enough' key set are offered to user). |\n| GRIST_ORG_IN_PATH | if true, encode org in path rather than domain |\n| GRIST_PAGE_TITLE_SUFFIX | a string to append to the end of the `\u003Ctitle>` in HTML documents. Defaults to `\" - Grist\"`. Set to `_blank` for no suffix at all. |\n| ~GRIST_PROXY_AUTH_HEADER~ | Deprecated, and interpreted as a synonym for GRIST_FORWARD_AUTH_HEADER. |\n| GRIST_REQUEST_TIMEOUT_MS | if set, override nodes's server.requestTimeout flag. |\n| GRIST_ROUTER_URL | optional url for an api that allows servers to be (un)registered with a load balancer |\n| GRIST_SERVE_SAME_ORIGIN | set to \"true\" to access home server and doc workers on the same protocol-host-port as the top-level page, same as for custom domains (careful, host header should be trustworthy) |\n| GRIST_SERVERS | the types of server to setup. Comma separated values which may contain \"home\", \"docs\", static\" and\u002For \"app\". Defaults to \"home,docs,static\". |\n| GRIST_SESSION_COOKIE | if set, overrides the name of Grist's cookie |\n| GRIST_SESSION_DOMAIN | if set, associates the cookie with the given domain - otherwise defaults to GRIST_DOMAIN |\n| GRIST_SESSION_SECRET | a key used to encode sessions |\n| GRIST_SKIP_BUNDLED_WIDGETS | if set, Grist will ignore any bundled widgets included via NPM packages. |\n| GRIST_SQLITE_MODE | if set to `wal`, use SQLite in [WAL mode](https:\u002F\u002Fwww.sqlite.org\u002Fwal.html), if set to `sync`, use SQLite with [SYNCHRONOUS=full](https:\u002F\u002Fwww.sqlite.org\u002Fpragma.html#pragma_synchronous)\n| GRIST_ANON_PLAYGROUND | When set to `false` deny anonymous users access to the home page (but documents can still be shared to anonymous users). Defaults to `true`, unless GRIST_ORG_CREATION_ANYONE is `false`. |\n| GRIST_FORCE_LOGIN | Setting it to `true` is similar to setting `GRIST_ANON_PLAYGROUND: false` but it blocks any anonymous access (thus any document shared publicly actually requires the users to be authenticated before consulting them) |\n| GRIST_PERSONAL_ORGS | When set to `false` prevent new personal orgs from being created when a user signs up. Defaults to `true`, unless GRIST_ORG_CREATION_ANYONE is `false`. |\n| GRIST_ORG_CREATION_ANYONE | When set to `false`, prevent new team orgs from being created by non-admin users. Sets default values of `GRIST_ANON_PLAYGROUND` and `GRIST_PERSONAL_ORGS` to `false`. Defaults to `true`. |\n| GRIST_SINGLE_ORG | set to an org \"domain\" to pin client to that org |\n| GRIST_TEMPLATE_ORG | set to an org \"domain\" to show public docs from that org |\n| GRIST_HELP_CENTER | set the help center link ref |\n| GRIST_TERMS_OF_SERVICE_URL | if set, adds terms of service link |\n| FREE_COACHING_CALL_URL | set the link to the human help (example: email adress or meeting scheduling tool) |\n| GRIST_CONTACT_SUPPORT_URL | set the link to contact support on error pages (example: email adress or online form) |\n| GRIST_ONBOARDING_VIDEO_ID | set the ID of the YouTube video shown on the homepage and during onboarding |\n| GRIST_CUSTOM_COMMON_URLS | overwrite the default commons URLs. Its value is expected to be a JSON object and a subset of the [ICommonUrls interface](.\u002Fapp\u002Fcommon\u002FICommonUrls.ts). |\n| GRIST_SUPPORT_ANON | if set to 'true', show UI for anonymous access (not shown by default) |\n| GRIST_SUPPORT_EMAIL | if set, give a user with the specified email support powers. The main extra power is the ability to share sites, workspaces, and docs with all users in a listed way. |\n| GRIST_OPEN_GRAPH_PREVIEW_IMAGE | the URL of the preview image when sharing the link on websites like social medias or chat applications. |\n| GRIST_TELEMETRY_LEVEL | the telemetry level. Can be set to: `off` (default), `limited`, or `full`. |\n| GRIST_THROTTLE_CPU | if set, CPU throttling is enabled |\n| GRIST_TRUST_PLUGINS | if set, plugins are expect to be served from the same host as the rest of the Grist app, rather than from a distinct host. Ordinarily, plugins are served from a distinct host so that the cookies used by the Grist app are not automatically available to them. Enable this only if you understand the security implications. |\n| GRIST_USER_ROOT | an extra path to look for plugins in - Grist will scan for plugins in `$GRIST_USER_ROOT\u002Fplugins`. |\n| GRIST_UI_FEATURES | comma-separated list of UI features to enable. Allowed names of parts: `helpCenter`, `billing`, `templates`, `createSite`, `multiSite`, `multiAccounts`, `importFromAirtable`, `sendToDrive`, `tutorials`, `supportGrist`, `themes`, `automations`. If a part also exists in GRIST_HIDE_UI_ELEMENTS, it won't be enabled. Note: `importFromAirtable` and `automations` are enabled by default even without being listed here; use GRIST_HIDE_UI_ELEMENTS to disable them. |\n| GRIST_UNTRUSTED_PORT | if set, plugins will be served from the given port. This is an alternative to setting APP_UNTRUSTED_URL. |\n| GRIST_WIDGET_LIST_URL | a url pointing to a widget manifest, by default https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-widget\u002Freleases\u002Fdownload\u002Flatest\u002Fmanifest.json is used |\n| GRIST_LOG_HTTP | When set to `true`, log HTTP requests and responses information. Defaults to `false`. |\n| GRIST_LOG_HTTP_BODY | When this variable and `GRIST_LOG_HTTP` are set to `true` , log the body along with the HTTP requests. :warning: Be aware it may leak confidential information in the logs.:warning: Defaults to `false`. |\n| GRIST_LOG_AS_JSON | When this variable is set to `true` or a truthy value, output log lines in JSON as opposed to a plain text format. |\n| GRIST_LOG_API_DETAILS | When this variable is set to `true` or a truthy value, log the API calls details. |\n| COOKIE_MAX_AGE | session cookie max age, defaults to 90 days; can be set to \"none\" to make it a session cookie |\n| HOME_PORT | port number to listen on for REST API server; if set to \"share\", add API endpoints to regular grist port. |\n| PORT | port number to listen on for Grist server |\n| REDIS_URL | optional redis server for browser sessions and db query caching |\n| GRIST_SNAPSHOT_TIME_CAP | optional. Define the caps for tracking buckets. Usage: {\"hour\": 25, \"day\": 32, \"isoWeek\": 12, \"month\": 96, \"year\": 1000} |\n| GRIST_SNAPSHOT_KEEP | optional. Number of recent snapshots to retain unconditionally for a document, regardless of when they were made |\n| GRIST_PROMCLIENT_PORT | optional. If set, serve the Prometheus metrics on the specified port number. ⚠️ Be sure to use a port which is not publicly exposed ⚠️. |\n| GRIST_ENABLE_SCIM | optional. If set, enable the [SCIM API Endpoint](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Fscim\u002F) (experimental) |\n| GRIST_LOGIN_SYSTEM_TYPE | optional. If set, explicitly selects which login system to use. Valid values: `saml`, `oidc`, `forward-auth`, `minimal`. If not set, Grist will automatically detect and use the first configured login system. |\n| GRIST_OIDC_... | optional. Environment variables used to configure OpenID authentification. See [OpenID Connect](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Foidc\u002F) documentation for full related list of environment variables. |\n| GRIST_SAML_... | optional. Environment variables used to configure SAML authentification. See [SAML](https:\u002F\u002Fsupport.getgrist.com\u002Finstall\u002Fsaml\u002F) documentation for full related list of environment variables. |\n| GRIST_IDP_EXTRA_PROPS | optional. If set, defines which extra fields returned by your identity provider will be stored in the users table of the home database (in the `options.ssoExtraInfo` object). Usage: 'onekey,anotherkey'. |\n| GRIST_FEATURE_FORM_FRAMING | optional. Configures a border around a rendered form that is added for security reasons; Can be set to: `border` or `minimal`. Defaults to `border`. |\n| GRIST_TRUTHY_VALUES | optional. Comma-separated list of extra words that should be considered as truthy by the data engine beyond english defaults. Ex: \"oui,ja,si\" |\n| GRIST_FALSY_VALUES | optional. Comma-separated list of extra words that should be considered as falsy by the data engine beyond english defaults. Ex: \"non,nein,no\" |\n| GRIST_ENABLE_USER_PRESENCE | optional, enabled by default. If set to 'false', disables all user presence features. |\n#### AI Formula Assistant related variables (all optional):\n\nVariable | Purpose\n-------- | -------\nASSISTANT_API_KEY   | optional. An API key to pass when making requests to an external AI conversational endpoint.\nASSISTANT_CHAT_COMPLETION_ENDPOINT  | optional. A chat-completion style endpoint to call. Not needed if OpenAI is being used.\nASSISTANT_MODEL     | optional. If set, this string is passed along in calls to the AI conversational endpoint.\nASSISTANT_LONGER_CONTEXT_MODEL     | optional. If set, requests that fail because of a context length limitation will be retried with this model set.\nOPENAI_API_KEY      | optional. Synonym for ASSISTANT_API_KEY that assumes an OpenAI endpoint is being used. Sign up for an account on OpenAI and then generate a secret key [here](https:\u002F\u002Fplatform.openai.com\u002Faccount\u002Fapi-keys).\n\nAt the time of writing, the AI Assistant is known to function against OpenAI chat completion endpoints (those ending in `\u002Fv1\u002Fchat\u002Fcompletions`).\nIt is also known to function against the chat completion endpoint provided by \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fabetlen\u002Fllama-cpp-python\">llama-cpp-python\u003C\u002Fa> and by [LM Studio](https:\u002F\u002Flmstudio.ai\u002F). For useful results, the LLM should be on par with GPT 3.5 or above.\n\n#### Sandbox related variables:\n\nVariable | Purpose | Sandbox |\n-------- | ------- | ------- |\nGRIST_SANDBOX_FLAVOR | can be gvisor, pynbox, unsandboxed, docker, or macSandboxExec. If set, forces Grist to use the specified kind of sandbox. | N\u002FA |\nGRIST_SANDBOX | a program or image name to run as the sandbox. See NSandbox.ts for nerdy details. | N\u002FA |\nGVISOR_LIMIT_NPROC | the number of extant processes the sandbox is allowed to spawn when running on Linux. Defaults to 8. | GVisor |\nGVISOR_LIMIT_MEMORY | the maximum size of the sandboxed process's virtual memory (in bytes). No limit by default. | GVisor |\n\n#### Forward authentication variables:\n\nVariable | Purpose\n-------- | -------\nGRIST_FORWARD_AUTH_HEADER | if set, trust the specified header (e.g. \"x-forwarded-user\") to contain authorized user emails, and enable \"forward auth\" logins.\nGRIST_FORWARD_AUTH_LOGIN_PATH | if GRIST_FORWARD_AUTH_HEADER is set, Grist will listen at this path for logins. Defaults to `\u002Fauth\u002Flogin`.\nGRIST_FORWARD_AUTH_LOGOUT_PATH | if GRIST_FORWARD_AUTH_HEADER is set, Grist will forward to this path when user logs out.\n\nForward authentication supports two modes, distinguished by `GRIST_IGNORE_SESSION`:\n\n1. With sessions, and forward-auth on login endpoints.\n\n   For example, using traefik reverse proxy with\n   [traefik-forward-auth](https:\u002F\u002Fgithub.com\u002Fthomseddon\u002Ftraefik-forward-auth) middleware:\n\n   - `GRIST_IGNORE_SESSION`: do NOT set, or set to a falsy value.\n   - Make sure your reverse proxy applies the forward auth middleware to\n     `GRIST_FORWARD_AUTH_LOGIN_PATH` and `GRIST_FORWARD_AUTH_LOGOUT_PATH`.\n   - If you want to allow anonymous access in some cases, make sure all other paths are free of\n     the forward auth middleware. Grist will trigger it as needed by redirecting to\n     `GRIST_FORWARD_AUTH_LOGIN_PATH`. Once the user is logged in, Grist will use sessions to\n     identify the user until logout.\n\n2. With no sessions, and forward-auth on all endpoints.\n\n   For example, using HTTP Basic Auth and server configuration that sets the header (specified in\n   `GRIST_FORWARD_AUTH_HEADER`) to the logged-in user.\n\n  - `GRIST_IGNORE_SESSION`: set to `true`. Grist sessions will not be used.\n  - Make sure your reverse proxy sets the header you specified for all requests that may need\n    login information. It is imperative that this header cannot be spoofed by the user, since\n    Grist will trust whatever is in it.\n\nWhen using forward authentication, you may wish to also set the following variables:\n\n  * `GRIST_FORCE_LOGIN=true` to disable anonymous access.\n\n#### Plugins:\n\nGrist has a plugin system, used internally. One useful thing you can\ndo with it is include custom widgets in a build of Grist. Custom widgets\nare usually made available just by setting `GRIST_WIDGET_LIST_URL`,\nbut that has the downside of being an external dependency, which can\nbe awkward for offline use or for archiving. Plugins offer an alternative.\n\nTo \"bundle\" custom widgets as a plugin:\n\n * Add a subdirectory of `plugins`, e.g. `plugins\u002Fmy-widgets`.\n   Alternatively, you can set the `GRIST_USER_ROOT` environment\n   variable to any path you want, and then create `plugins\u002Fmy-widgets`\n   within that.\n * Add a `manifest.yml` file in that subdirectory that looks like\n   this:\n\n```\nname: My Widgets\ncomponents:\n  widgets: widgets.json\n```\n\n * The `widgets.json` file should be in the format produced by\n   the [grist-widget](https:\u002F\u002Fgithub.com\u002Fgristlabs\u002Fgrist-widget)\n   repository, and should be placed in the same directory as\n   `manifest.yml`. Any material in `plugins\u002Fmy-widgets`\n   will be served by Grist, and relative URLs can be used in\n   `widgets.json`.\n * Once all files are in place, restart Grist. Your widgets should\n   now be available in the custom widgets dropdown, along with\n   any others from `GRIST_WIDGET_LIST_URL`.\n * If you like, you can add multiple plugin subdirectories, with\n   multiple sets of widgets, and they'll all be made available.\n\n#### Google Drive integrations:\n\nVariable | Purpose\n-------- | -------\nGOOGLE_CLIENT_ID    | set to the Google Client Id to be used with Google API client\nGOOGLE_CLIENT_SECRET| set to the Google Client Secret to be used with Google API client\nGOOGLE_API_KEY      | set to the Google API Key to be used with Google API client (accessing public files)\nGOOGLE_DRIVE_SCOPE  | set to the scope requested for Google Drive integration (defaults to drive.file)\n\n#### Database variables:\n\nVariable | Purpose\n-------- | -------\nTYPEORM_DATABASE | database filename for sqlite or database name for other db types\nTYPEORM_HOST     | host for db\nTYPEORM_LOGGING  | set to 'true' to see all sql queries\nTYPEORM_PASSWORD | password to use\nTYPEORM_PORT     | port number for db if not the default for that db type\nTYPEORM_TYPE     | set to 'sqlite' or 'postgres'\nTYPEORM_USERNAME | username to connect as\nTYPEORM_EXTRA    | any other properties to pass to TypeORM in JSON format\n\n#### Docker-only variables:\n\nVariable | Purpose\n---------|--------\nGRIST_DOCKER_USER  | optional. When the container runs as the root user, this is the user the Grist services run as. Overrides the default.\nGRIST_DOCKER_GROUP | optional. When the container runs as the root user, this is the group the Grist services run as. Overrides the default.\n\n#### Testing:\n\nVariable | Purpose\n-------- | -------\nGRIST_TESTING_SOCKET    | a socket used for out-of-channel communication during tests only.\nGRIST_TEST_FORCE_LIGHT_MODE | if set, Grist will use light mode even if system preference is dark. Some tests just assume light mode.\nGRIST_TEST_HTTPS_OFFSET | if set, adds https ports at the specified offset.  This is useful in testing.\nGRIST_TEST_SSL_CERT     | if set, contains filename of SSL certificate.\nGRIST_TEST_SSL_KEY      | if set, contains filename of SSL private key.\nGRIST_TEST_LOGIN        | allow fake unauthenticated test logins (suitable for dev environment only).\nGRIST_TEST_ROUTER       | if set, then the home server will serve a mock version of router api at \u002Ftest\u002Frouter\nGREP_TESTS              | pattern for selecting specific tests to run (e.g. `env GREP_TESTS=ActionLog yarn test`).\n\n## Tests\n\nTests are run automatically as part of CI when a PR is opened. However, it can be helpful to run tests locally\nbefore pushing your changes to GitHub. First, you'll want to make sure you've installed all dependencies:\n\n```\nyarn install\nyarn install:python\n```\n\nThen, you can run the main test suite like so:\n\n```\nyarn test\n```\n\nPython tests may also be run locally. (Note: currently requires Python 3.10 - 3.11.)\n\n```\nyarn test:python\n```\n\nFor running specific tests, you can specify a pattern with the `GREP_TESTS` variable:\n\n```\nenv GREP_TESTS=ChoiceList yarn test\nenv GREP_TESTS=summary yarn test:python\n```\n\n## License\n\nThis repository, `grist-core`, is released under the [Apache License, Version 2.0](http:\u002F\u002Fwww.apache.org\u002Flicenses\u002FLICENSE-2.0), which is an [OSI](https:\u002F\u002Fopensource.org\u002F)-approved free software license. See LICENSE.txt and NOTICE.txt for more information.\n","Grist 是一款现代的关系型电子表格，它结合了电子表格的灵活性和数据库的稳健性。其核心功能包括支持列命名及单一类型数据存储、公式填充与自动更新等特性，这些都使得 Grist 成为一个强大的数据管理工具。项目使用 TypeScript 编写，并且开源（Apache License 2.0），主要分为三个部分：`grist-core` 提供了一个强大的服务器来托管电子表格；`grist-desktop` 支持本地查看与编辑；而 `grist-static` 则可以在无后端支持的情况下于网页中展示电子表格。Grist 非常适合需要高效处理复杂数据但又希望保持操作简便性的团队或个人使用，尤其是在数据分析、项目管理和业务流程自动化等领域。",2,"2026-06-11 03:28:13","top_topic"]