├── .changeset
├── README.md
└── config.json
├── .eslintignore
├── .eslintrc.js
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ └── config.yml
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
└── workflows
│ ├── close-v2-issues.yml
│ ├── deduplicate-lock-file.yml
│ ├── deployments.yml
│ ├── format.yml
│ ├── lint.yml
│ ├── merged-pr.yml
│ ├── nightly.yml
│ ├── no-response.yml
│ ├── release-comments.yml
│ ├── release-experimental.yml
│ ├── release.yml
│ ├── shared-build.yml
│ ├── shared-test-integration.yml
│ ├── shared-test-unit.yml
│ ├── stacks.yml
│ ├── test-full.yml
│ ├── test-pr-ubuntu.yml
│ ├── test-pr-windows-macos.yml
│ └── website.yml
├── .gitignore
├── .npmrc
├── .nvmrc
├── .prettierignore
├── .vscode
├── README.md
├── deno_resolve_npm_imports.json
├── extensions.json
└── settings.json
├── CHANGELOG.md
├── CLA.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── DEVELOPMENT.md
├── LICENSE.md
├── README.md
├── babel.config.js
├── contributors.yml
├── decisions
├── 0001-use-npm-to-manage-npm-dependencies-for-deno-projects.md
├── 0002-do-not-clone-request.md
├── 0003-infer-types-for-useloaderdata-and-useactiondata-from-loader-and-action-via-generics.md
├── 0004-streaming-apis.md
├── 0005-remixing-react-router.md
├── 0006-linear-workflow.md
├── 0007-remix-on-react-router-6-4-0.md
├── 0008-only-support-js-conversion-for-app-code.md
├── 0009-do-not-rely-on-treeshaking-for-correctness.md
├── 0010-splitting-up-client-and-server-code-in-vite.md
└── template.md
├── docs
├── components
│ ├── await.md
│ ├── form.md
│ ├── index.md
│ ├── link.md
│ ├── links.md
│ ├── live-reload.md
│ ├── meta.md
│ ├── nav-link.md
│ ├── outlet.md
│ ├── prefetch-page-links.md
│ ├── scripts.md
│ └── scroll-restoration.md
├── discussion
│ ├── component-data.md
│ ├── concurrency.md
│ ├── cookies-and-sessions.md
│ ├── data-flow.md
│ ├── error-handling.md
│ ├── form-validation.md
│ ├── form-vs-fetcher.md
│ ├── formdata.md
│ ├── hot-module-replacement.md
│ ├── html-forms.md
│ ├── index.md
│ ├── introduction.md
│ ├── multiple-forms.md
│ ├── nested-routes.md
│ ├── pending-ui.md
│ ├── progressive-enhancement.md
│ ├── react-router.md
│ ├── resubmissions.md
│ ├── routes.md
│ ├── runtimes.md
│ ├── server-vs-client.md
│ ├── state-management.md
│ └── testing.md
├── file-conventions
│ ├── -client.md
│ ├── -server.md
│ ├── asset-imports.md
│ ├── entry.client.md
│ ├── entry.server.md
│ ├── index.md
│ ├── remix-config.md
│ ├── root.md
│ ├── routes.md
│ └── vite-config.md
├── guides
│ ├── accessibility.md
│ ├── api-development-strategy.md
│ ├── api-routes.md
│ ├── authentication.md
│ ├── bff.md
│ ├── breadcrumbs.md
│ ├── browser-support.md
│ ├── cache-control.md
│ ├── client-data.md
│ ├── concurrent-submissions.md
│ ├── constraints.md
│ ├── contributing.md
│ ├── css-files.md
│ ├── data-loading.md
│ ├── data-writes.md
│ ├── debugging.md
│ ├── dependency-optimization.md
│ ├── deployment.md
│ ├── disabling-javascript.md
│ ├── envvars.md
│ ├── errors.md
│ ├── faq.md
│ ├── file-uploads.md
│ ├── form-validation.md
│ ├── gotchas.md
│ ├── images.md
│ ├── index-query-param.md
│ ├── index.md
│ ├── lazy-route-discovery.md
│ ├── local-tls.md
│ ├── manual-mode.md
│ ├── mdx.md
│ ├── meta.md
│ ├── migrating-react-router-app.md
│ ├── not-found.md
│ ├── performance.md
│ ├── presets.md
│ ├── progressive-enhancement.md
│ ├── resource-routes.md
│ ├── server-bundles.md
│ ├── single-fetch.md
│ ├── spa-mode.md
│ ├── streaming.md
│ ├── templates.md
│ ├── typescript.md
│ └── vite.md
├── hooks
│ ├── index.md
│ ├── use-action-data.md
│ ├── use-async-error.md
│ ├── use-async-value.md
│ ├── use-before-unload.md
│ ├── use-blocker.md
│ ├── use-fetcher.md
│ ├── use-fetchers.md
│ ├── use-form-action.md
│ ├── use-href.md
│ ├── use-loader-data.md
│ ├── use-location.md
│ ├── use-matches.md
│ ├── use-navigate.md
│ ├── use-navigation-type.md
│ ├── use-navigation.md
│ ├── use-outlet-context.md
│ ├── use-outlet.md
│ ├── use-params.md
│ ├── use-prompt.md
│ ├── use-resolved-path.md
│ ├── use-revalidator.md
│ ├── use-route-error.md
│ ├── use-route-loader-data.md
│ ├── use-search-params.md
│ ├── use-submit.md
│ └── use-view-transition-state.md
├── index.md
├── other-api
│ ├── adapter.md
│ ├── create-remix.md
│ ├── dev.md
│ ├── index.md
│ ├── node.md
│ ├── serve.md
│ └── testing.md
├── prettier.config.js
├── route
│ ├── action.md
│ ├── client-action.md
│ ├── client-loader.md
│ ├── component.md
│ ├── error-boundary.md
│ ├── handle.md
│ ├── headers.md
│ ├── hydrate-fallback.md
│ ├── index.md
│ ├── links.md
│ ├── loader.md
│ ├── meta.md
│ └── should-revalidate.md
├── start
│ ├── changelog.md
│ ├── community.md
│ ├── future-flags.md
│ ├── index.md
│ ├── quickstart.md
│ ├── tutorial.md
│ └── v2.md
├── styling
│ ├── bundling.md
│ ├── css-imports.md
│ ├── css-in-js.md
│ ├── css-modules.md
│ ├── css.md
│ ├── index.md
│ ├── postcss.md
│ ├── tailwind.md
│ └── vanilla-extract.md
├── tutorials
│ ├── blog.md
│ ├── index.md
│ └── jokes.md
└── utils
│ ├── cookies.md
│ ├── create-remix-stub.md
│ ├── data.md
│ ├── defer.md
│ ├── index.md
│ ├── is-route-error-response.md
│ ├── json.md
│ ├── parse-multipart-form-data.md
│ ├── redirect.md
│ ├── redirectDocument.md
│ ├── replace.md
│ ├── sessions.md
│ ├── unstable-create-file-upload-handler.md
│ └── unstable-create-memory-upload-handler.md
├── examples
└── README.md
├── integration
├── CHANGELOG.md
├── abort-signal-test.ts
├── action-test.ts
├── assets
│ ├── toupload.txt
│ └── touploadtoobig.txt
├── blocking-test.ts
├── browser-entry-test.ts
├── bug-report-test.ts
├── catch-boundary-data-test.ts
├── catch-boundary-test.ts
├── cf-compiler-test.ts
├── client-data-test.ts
├── compiler-mjs-cjs-output-test.ts
├── compiler-test.ts
├── css-modules-test.ts
├── css-side-effect-imports-test.ts
├── custom-entry-server-test.ts
├── defer-loader-test.ts
├── defer-test.ts
├── deno-compiler-test.ts
├── deterministic-build-output-test.ts
├── error-boundary-test.ts
├── error-boundary-v2-test.ts
├── error-data-request-test.ts
├── error-sanitization-test.ts
├── fetch-globals-test.ts
├── fetcher-layout-test.ts
├── fetcher-test.ts
├── file-uploads-test.ts
├── flat-routes-test.ts
├── fog-of-war-test.ts
├── form-data-test.ts
├── form-test.ts
├── headers-test.ts
├── helpers
│ ├── cf-template
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── root.tsx
│ │ │ └── routes
│ │ │ │ └── _index.tsx
│ │ ├── package.json
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── remix.config.js
│ │ ├── remix.env.d.ts
│ │ ├── server.ts
│ │ ├── tsconfig.json
│ │ └── wrangler.toml
│ ├── cleanup.mjs
│ ├── create-fixture.ts
│ ├── deno-template
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── root.tsx
│ │ │ └── routes
│ │ │ │ └── _index.tsx
│ │ ├── package.json
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── remix.config.js
│ │ └── server.ts
│ ├── killtree.ts
│ ├── node-template
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── root.tsx
│ │ │ └── routes
│ │ │ │ └── _index.tsx
│ │ ├── package.json
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── remix.config.js
│ │ ├── remix.env.d.ts
│ │ └── tsconfig.json
│ ├── playwright-fixture.ts
│ ├── vite-5-template
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── root.tsx
│ │ │ └── routes
│ │ │ │ └── _index.tsx
│ │ ├── env.d.ts
│ │ ├── package.json
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── tsconfig.json
│ │ └── vite.config.ts
│ ├── vite-6-template
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── root.tsx
│ │ │ └── routes
│ │ │ │ └── _index.tsx
│ │ ├── env.d.ts
│ │ ├── package.json
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── tsconfig.json
│ │ └── vite.config.ts
│ ├── vite-cloudflare-template
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── root.tsx
│ │ │ └── routes
│ │ │ │ └── _index.tsx
│ │ ├── env.d.ts
│ │ ├── package.json
│ │ ├── public
│ │ │ └── favicon.ico
│ │ ├── tsconfig.json
│ │ └── vite.config.ts
│ └── vite.ts
├── hmr-test.ts
├── hook-useSubmit-test.ts
├── js-routes-test.ts
├── layout-route-test.ts
├── link-test.ts
├── loader-test.ts
├── matches-test.ts
├── mdx-test.ts
├── multiple-cookies-test.ts
├── navigation-state-test.ts
├── package.json
├── path-mapping-test.ts
├── playwright.config.ts
├── postcss-test.ts
├── prefetch-test.ts
├── redirects-test.ts
├── remix-serve-test.ts
├── rendering-test.ts
├── request-test.ts
├── resource-routes-test.ts
├── revalidate-test.ts
├── root-route-test.ts
├── route-collisions-test.ts
├── scroll-test.ts
├── server-code-in-browser-message-test.ts
├── server-entry-test.ts
├── server-source-maps-test.ts
├── set-cookie-revalidation-test.ts
├── shared-route-imports-test.ts
├── single-fetch-test.ts
├── splat-routes-test.ts
├── svg-in-node-modules-test.ts
├── tailwind-test.ts
├── transition-test.ts
├── tsconfig.json
├── upload-test.ts
├── vanilla-extract-test.ts
├── vite-absolute-base-test.ts
├── vite-basename-test.ts
├── vite-build-test.ts
├── vite-cloudflare-test.ts
├── vite-css-test.ts
├── vite-dev-custom-entry-test.ts
├── vite-dev-test.ts
├── vite-dot-client-test.ts
├── vite-dot-server-test.ts
├── vite-dotenv-test.ts
├── vite-fs-routes-test.ts
├── vite-hmr-hdr-test.ts
├── vite-loader-context-test.ts
├── vite-manifests-test.ts
├── vite-node-env-test.ts
├── vite-plugin-order-validation-test.ts
├── vite-presets-test.ts
├── vite-route-added-test.ts
├── vite-route-config-test.ts
├── vite-route-exports-modified-offscreen-test.ts
├── vite-server-bundles-test.ts
├── vite-server-fs-allow-test.ts
├── vite-spa-mode-test.ts
└── vite-unused-route-exports-test.ts
├── jest.config.js
├── jest
├── buildRemix.js
├── jest.config.shared.js
└── transform.js
├── package.json
├── packages
├── ADDING_A_PACKAGE.md
├── create-remix
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ ├── create-remix-test.ts
│ │ ├── fixtures
│ │ │ ├── arc.tar.gz
│ │ │ ├── arc.tgz
│ │ │ ├── blank
│ │ │ │ └── package.json
│ │ │ ├── examples-main.tar.gz
│ │ │ ├── failing-remix-init
│ │ │ │ ├── package.json
│ │ │ │ └── remix.init
│ │ │ │ │ └── index.js
│ │ │ ├── nested-dir-repo.tar.gz
│ │ │ ├── remix-repo.tar.gz
│ │ │ ├── stack.tar.gz
│ │ │ ├── stack
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── app
│ │ │ │ │ ├── entry.client.tsx
│ │ │ │ │ ├── entry.server.tsx
│ │ │ │ │ ├── root.tsx
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── package.json
│ │ │ │ ├── public
│ │ │ │ │ └── favicon.ico
│ │ │ │ ├── remix.config.js
│ │ │ │ ├── remix.env.d.ts
│ │ │ │ ├── remix.init
│ │ │ │ │ └── index.js
│ │ │ │ └── tsconfig.json
│ │ │ ├── successful-remix-init
│ │ │ │ ├── package.json
│ │ │ │ └── remix.init
│ │ │ │ │ └── index.js
│ │ │ ├── tar.js
│ │ │ └── with-ignored-dir
│ │ │ │ └── package.json
│ │ ├── github-mocks.ts
│ │ ├── msw-register.ts
│ │ ├── msw.ts
│ │ └── setupAfterEnv.ts
│ ├── cli.ts
│ ├── copy-template.ts
│ ├── index.ts
│ ├── jest.config.js
│ ├── loading-indicator.ts
│ ├── package.json
│ ├── prompt.ts
│ ├── prompts-confirm.ts
│ ├── prompts-multi-select.ts
│ ├── prompts-prompt-base.ts
│ ├── prompts-select.ts
│ ├── prompts-text.ts
│ ├── rollup.config.js
│ ├── tsconfig.json
│ └── utils.ts
├── remix-architect
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ ├── 554828.jpeg
│ │ ├── binaryTypes-test.ts
│ │ ├── server-test.ts
│ │ └── setup.ts
│ ├── binaryTypes.ts
│ ├── index.ts
│ ├── jest.config.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── server.ts
│ ├── sessions
│ │ └── arcTableSessionStorage.ts
│ └── tsconfig.json
├── remix-cloudflare-pages
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ ├── rollup.config.js
│ ├── tsconfig.json
│ └── worker.ts
├── remix-cloudflare-workers
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ ├── rollup.config.js
│ ├── tsconfig.json
│ └── worker.ts
├── remix-cloudflare
│ ├── CHANGELOG.md
│ ├── crypto.ts
│ ├── globals.ts
│ ├── implementations.ts
│ ├── index.ts
│ ├── package.json
│ ├── rollup.config.js
│ ├── sessions
│ │ └── workersKVStorage.ts
│ └── tsconfig.json
├── remix-css-bundle
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ ├── rollup.config.js
│ └── tsconfig.json
├── remix-deno
│ ├── .empty.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── crypto.ts
│ ├── globals.ts
│ ├── implementations.ts
│ ├── index.ts
│ ├── package.json
│ ├── rollup.config.js
│ ├── server.ts
│ └── sessions
│ │ └── fileStorage.ts
├── remix-dev
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ ├── cli-test.ts
│ │ ├── cssSideEffectImports-test.ts
│ │ ├── defineRoutes-test.ts
│ │ ├── fixtures
│ │ │ ├── cloudflare
│ │ │ │ ├── .gitignore
│ │ │ │ ├── .node-version
│ │ │ │ ├── README.md
│ │ │ │ ├── app
│ │ │ │ │ ├── root.tsx
│ │ │ │ │ └── routes
│ │ │ │ │ │ └── _index.tsx
│ │ │ │ ├── package.json
│ │ │ │ ├── public
│ │ │ │ │ ├── _headers
│ │ │ │ │ ├── _routes.json
│ │ │ │ │ └── favicon.ico
│ │ │ │ ├── remix.config.js
│ │ │ │ ├── remix.env.d.ts
│ │ │ │ ├── server.ts
│ │ │ │ └── tsconfig.json
│ │ │ ├── deno
│ │ │ │ ├── .gitignore
│ │ │ │ ├── .vscode
│ │ │ │ │ ├── extensions.json
│ │ │ │ │ ├── resolve_npm_imports.json
│ │ │ │ │ └── settings.json
│ │ │ │ ├── README.md
│ │ │ │ ├── app
│ │ │ │ │ ├── root.tsx
│ │ │ │ │ └── routes
│ │ │ │ │ │ └── _index.tsx
│ │ │ │ ├── deno.json
│ │ │ │ ├── package.json
│ │ │ │ ├── public
│ │ │ │ │ └── favicon.ico
│ │ │ │ ├── remix.config.js
│ │ │ │ └── server.ts
│ │ │ ├── examples-main.tar.gz
│ │ │ ├── failing-remix-init
│ │ │ │ ├── package.json
│ │ │ │ └── remix.init
│ │ │ │ │ └── index.js
│ │ │ ├── nested-dir-repo.tar.gz
│ │ │ ├── node
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── app
│ │ │ │ │ ├── root.tsx
│ │ │ │ │ └── routes
│ │ │ │ │ │ └── _index.tsx
│ │ │ │ ├── package.json
│ │ │ │ ├── public
│ │ │ │ │ └── favicon.ico
│ │ │ │ ├── remix.config.js
│ │ │ │ ├── remix.env.d.ts
│ │ │ │ └── tsconfig.json
│ │ │ ├── remix-repo.tar.gz
│ │ │ ├── stack.tar.gz
│ │ │ ├── stack
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── app
│ │ │ │ │ ├── entry.client.tsx
│ │ │ │ │ ├── entry.server.tsx
│ │ │ │ │ ├── root.tsx
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── package.json
│ │ │ │ ├── public
│ │ │ │ │ └── favicon.ico
│ │ │ │ ├── remix.config.js
│ │ │ │ ├── remix.env.d.ts
│ │ │ │ ├── remix.init
│ │ │ │ │ └── index.js
│ │ │ │ └── tsconfig.json
│ │ │ ├── successful-remix-init
│ │ │ │ ├── package.json
│ │ │ │ └── remix.init
│ │ │ │ │ └── index.js
│ │ │ └── tar.js
│ │ ├── flat-routes-test.ts
│ │ ├── github-mocks.ts
│ │ ├── init-test.ts
│ │ ├── msw.ts
│ │ ├── readConfig-test.ts
│ │ ├── reveal-test.ts
│ │ ├── routeManifestToRouteConfig-test.ts
│ │ ├── setupAfterEnv.ts
│ │ ├── styles-test.ts
│ │ ├── utils
│ │ │ ├── captureError.ts
│ │ │ ├── cli.ts
│ │ │ ├── eol.ts
│ │ │ ├── git.ts
│ │ │ └── withApp.ts
│ │ └── validateRouteConfig-test.ts
│ ├── assets-manifest.d.ts
│ ├── cache.ts
│ ├── channel.ts
│ ├── cli.ts
│ ├── cli
│ │ ├── commands.ts
│ │ ├── detectPackageManager.ts
│ │ ├── index.ts
│ │ ├── run.ts
│ │ └── useJavascript.ts
│ ├── colors.ts
│ ├── compiler
│ │ ├── analysis.ts
│ │ ├── build.ts
│ │ ├── cancel.ts
│ │ ├── compiler.ts
│ │ ├── context.ts
│ │ ├── css
│ │ │ ├── bundle.ts
│ │ │ ├── compiler.ts
│ │ │ ├── index.ts
│ │ │ └── plugins
│ │ │ │ └── bundleEntry.ts
│ │ ├── fileWatchCache.ts
│ │ ├── index.ts
│ │ ├── js
│ │ │ ├── compiler.ts
│ │ │ ├── index.ts
│ │ │ ├── plugins
│ │ │ │ ├── browserNodeBuiltinsPolyfill.ts
│ │ │ │ ├── hmr.ts
│ │ │ │ └── routes.ts
│ │ │ └── write.ts
│ │ ├── lazyValue.ts
│ │ ├── manifest.ts
│ │ ├── options.ts
│ │ ├── plugins
│ │ │ ├── absoluteCssUrlsPlugin.ts
│ │ │ ├── cssBundlePlugin.ts
│ │ │ ├── cssImports.ts
│ │ │ ├── cssModuleImports.ts
│ │ │ ├── cssSideEffectImports.ts
│ │ │ ├── emptyModules.ts
│ │ │ ├── external.ts
│ │ │ ├── mdx.ts
│ │ │ └── vanillaExtract.ts
│ │ ├── server
│ │ │ ├── compiler.ts
│ │ │ ├── index.ts
│ │ │ ├── plugins
│ │ │ │ ├── bareImports.ts
│ │ │ │ ├── entry.ts
│ │ │ │ ├── manifest.ts
│ │ │ │ ├── routes.ts
│ │ │ │ └── serverNodeBuiltinsPolyfill.ts
│ │ │ ├── virtualModules.ts
│ │ │ └── write.ts
│ │ ├── utils
│ │ │ ├── crypto.ts
│ │ │ ├── loaders.ts
│ │ │ ├── log.ts
│ │ │ ├── postcss.ts
│ │ │ ├── routeExports.ts
│ │ │ └── tsconfig.ts
│ │ └── watch.ts
│ ├── config.ts
│ ├── config
│ │ ├── defaults
│ │ │ ├── entry.client.tsx
│ │ │ ├── entry.dev.ts
│ │ │ ├── entry.server.cloudflare.tsx
│ │ │ ├── entry.server.deno.tsx
│ │ │ ├── entry.server.node.tsx
│ │ │ └── entry.server.spa.tsx
│ │ ├── flat-routes.ts
│ │ ├── format.ts
│ │ ├── routes.ts
│ │ └── serverModes.ts
│ ├── dependencies.ts
│ ├── devServer
│ │ ├── index.ts
│ │ └── liveReload.ts
│ ├── devServer_unstable
│ │ ├── env.ts
│ │ ├── hdr.ts
│ │ ├── hmr.ts
│ │ ├── index.ts
│ │ ├── proc.ts
│ │ └── socket.ts
│ ├── index.ts
│ ├── invariant.ts
│ ├── jest.config.js
│ ├── manifest.ts
│ ├── modules.ts
│ ├── package.json
│ ├── result.ts
│ ├── rollup.config.js
│ ├── server-build.ts
│ ├── tsconfig.json
│ ├── tux
│ │ ├── format.ts
│ │ ├── index.ts
│ │ └── logger.ts
│ └── vite
│ │ ├── babel.ts
│ │ ├── build.ts
│ │ ├── cloudflare-proxy-plugin.ts
│ │ ├── combine-urls-test.ts
│ │ ├── combine-urls.ts
│ │ ├── dev.ts
│ │ ├── index.ts
│ │ ├── is-in-remix-monorepo.ts
│ │ ├── node-adapter.ts
│ │ ├── plugin.ts
│ │ ├── profiler.ts
│ │ ├── remove-exports-test.ts
│ │ ├── remove-exports.ts
│ │ ├── resolve-file-url.ts
│ │ ├── ssr-externals.ts
│ │ ├── static
│ │ └── refresh-utils.cjs
│ │ ├── styles.ts
│ │ ├── vite-node.ts
│ │ ├── vite.ts
│ │ └── vmod.ts
├── remix-eslint-config
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.js
│ ├── internal.js
│ ├── jest-testing-library.js
│ ├── node.js
│ ├── package.json
│ ├── rules
│ │ ├── core.js
│ │ ├── import.js
│ │ ├── jest-dom.js
│ │ ├── jest.js
│ │ ├── jsx-a11y.js
│ │ ├── react.js
│ │ ├── testing-library.js
│ │ └── typescript.js
│ └── settings
│ │ ├── import.js
│ │ └── react.js
├── remix-express
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ ├── server-test.ts
│ │ └── setup.ts
│ ├── index.ts
│ ├── jest.config.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── server.ts
│ └── tsconfig.json
├── remix-fs-routes
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ ├── rollup.config.js
│ └── tsconfig.json
├── remix-node
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ ├── assets
│ │ │ └── test.txt
│ │ ├── fileUploadHandler-test.ts
│ │ ├── sessions-test.ts
│ │ ├── setup.ts
│ │ └── utils.ts
│ ├── crypto.ts
│ ├── globals.ts
│ ├── implementations.ts
│ ├── index.ts
│ ├── install.d.ts
│ ├── install.js
│ ├── jest.config.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── sessions
│ │ └── fileStorage.ts
│ ├── stream.ts
│ ├── tsconfig.json
│ └── upload
│ │ └── fileUploadHandler.ts
├── remix-react
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ ├── components-test.tsx
│ │ ├── deferred-scripts-test.tsx
│ │ ├── exports-test.tsx
│ │ ├── integration
│ │ │ └── meta-test.tsx
│ │ ├── scroll-restoration-test.tsx
│ │ └── setup.ts
│ ├── browser.tsx
│ ├── components.tsx
│ ├── data.ts
│ ├── entry.ts
│ ├── errorBoundaries.tsx
│ ├── errors.ts
│ ├── fallback.tsx
│ ├── fog-of-war.ts
│ ├── index.tsx
│ ├── invariant.ts
│ ├── jest.config.js
│ ├── links.ts
│ ├── markup.ts
│ ├── package.json
│ ├── rollup.config.js
│ ├── routeModules.ts
│ ├── routes.tsx
│ ├── scroll-restoration.tsx
│ ├── server.tsx
│ ├── single-fetch.tsx
│ ├── tsconfig.json
│ └── warnings.ts
├── remix-route-config
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ └── route-config-test.ts
│ ├── index.ts
│ ├── jest.config.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── routes.ts
│ └── tsconfig.json
├── remix-routes-option-adapter
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ ├── rollup.config.js
│ └── tsconfig.json
├── remix-serve
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── cli.ts
│ ├── package.json
│ ├── rollup.config.js
│ └── tsconfig.json
├── remix-server-runtime
│ ├── .eslintrc.js
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ ├── .eslintrc.js
│ │ ├── cookies-test.ts
│ │ ├── data-test.ts
│ │ ├── formData-test.ts
│ │ ├── handle-error-test.ts
│ │ ├── handler-test.ts
│ │ ├── markup-test.ts
│ │ ├── responses-test.ts
│ │ ├── serialize-test.ts
│ │ ├── server-test.ts
│ │ ├── sessions-test.ts
│ │ ├── setup.ts
│ │ └── utils.ts
│ ├── build.ts
│ ├── cookies.ts
│ ├── crypto.ts
│ ├── data.ts
│ ├── deprecations.ts
│ ├── dev.ts
│ ├── entry.ts
│ ├── errors.ts
│ ├── formData.ts
│ ├── future.ts
│ ├── headers.ts
│ ├── index.ts
│ ├── interface.ts
│ ├── invariant.ts
│ ├── jest.config.js
│ ├── jsonify.ts
│ ├── links.ts
│ ├── markup.ts
│ ├── mode.ts
│ ├── package.json
│ ├── reexport.ts
│ ├── responses.ts
│ ├── rollup.config.js
│ ├── routeMatching.ts
│ ├── routeModules.ts
│ ├── routes.ts
│ ├── serialize.ts
│ ├── server.ts
│ ├── serverHandoff.ts
│ ├── sessions.ts
│ ├── sessions
│ │ ├── cookieStorage.ts
│ │ └── memoryStorage.ts
│ ├── single-fetch.ts
│ ├── tsconfig.json
│ ├── typecheck.ts
│ ├── upload
│ │ ├── errors.ts
│ │ └── memoryUploadHandler.ts
│ └── warnings.ts
├── remix-testing
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── __tests__
│ │ └── stub-test.tsx
│ ├── create-remix-stub.tsx
│ ├── index.ts
│ ├── jest.config.js
│ ├── jest.setup.js
│ ├── package.json
│ ├── rollup.config.js
│ └── tsconfig.json
└── remix
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ ├── rollup.config.js
│ └── tsconfig.json
├── patches
└── @changesets__assemble-release-plan@5.2.2.patch
├── playground
└── README.md
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── prettier.config.js
├── rollup.config.js
├── rollup.utils.js
├── scripts
├── build.mjs
├── bump-fetch-versions.sh
├── bump-router-versions.sh
├── clean-build.mjs
├── close-v2-issues-comment.md
├── close-v2-issues.mjs
├── close-v2-prs-comment.md
├── compile-release-notes.mjs
├── copy-build-to-dist.mjs
├── copy-templates-to-fixtures.sh
├── deployment-test
│ ├── _shared.mjs
│ ├── arc.mjs
│ ├── cf-pages.mjs
│ ├── cf-workers.mjs
│ ├── cypress.json
│ ├── cypress
│ │ ├── .eslintrc.js
│ │ ├── e2e
│ │ │ └── smoke.ts
│ │ ├── fixtures
│ │ │ └── example.json
│ │ ├── plugins
│ │ │ └── index.ts
│ │ ├── support
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── deno-deploy.mjs
│ ├── fly.mjs
│ └── package.json
├── find-release-from-changeset.js
├── lint-templates.sh
├── markdown-references.mjs
├── patchup-version.mjs
├── playground
│ ├── new.js
│ └── template
│ │ ├── .env
│ │ ├── .gitignore
│ │ ├── .prettierignore
│ │ ├── README.md
│ │ ├── app
│ │ ├── db.server.ts
│ │ ├── entry.client.tsx
│ │ ├── entry.server.tsx
│ │ ├── models
│ │ │ ├── note.server.ts
│ │ │ └── user.server.ts
│ │ ├── root.tsx
│ │ ├── routes
│ │ │ ├── index.tsx
│ │ │ ├── join.tsx
│ │ │ ├── login.tsx
│ │ │ ├── logout.tsx
│ │ │ ├── notes.tsx
│ │ │ └── notes
│ │ │ │ ├── $noteId.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── new.tsx
│ │ ├── session.server.ts
│ │ ├── styles
│ │ │ └── tailwind.css
│ │ └── utils.ts
│ │ ├── package.json
│ │ ├── prisma
│ │ ├── migrations
│ │ │ ├── 20220307190657_init
│ │ │ │ └── migration.sql
│ │ │ └── migration_lock.toml
│ │ ├── schema.prisma
│ │ └── seed.ts
│ │ ├── public
│ │ └── favicon.ico
│ │ ├── remix.config.js
│ │ ├── remix.env.d.ts
│ │ ├── remix.init
│ │ └── index.js
│ │ ├── server.js
│ │ ├── tailwind.config.js
│ │ └── tsconfig.json
├── prompt-confirm.d.ts
├── publish-private.js
├── publish.js
├── release.js
├── remove-prerelease-changelogs.mjs
├── run-migration-on-examples.js
├── tsconfig.json
├── unist.d.ts
├── utils.js
└── version.js
└── templates
├── .eslintignore
├── .gitignore
├── classic-remix-compiler
├── arc
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── README.md
│ ├── app.arc
│ ├── app
│ │ ├── entry.client.tsx
│ │ ├── entry.server.tsx
│ │ ├── root.tsx
│ │ └── routes
│ │ │ └── _index.tsx
│ ├── package.json
│ ├── plugin-remix.js
│ ├── public
│ │ └── favicon.ico
│ ├── remix.config.js
│ ├── remix.env.d.ts
│ ├── server.ts
│ └── tsconfig.json
├── cloudflare-pages
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── .node-version
│ ├── README.md
│ ├── app
│ │ ├── entry.client.tsx
│ │ ├── entry.server.tsx
│ │ ├── root.tsx
│ │ └── routes
│ │ │ └── _index.tsx
│ ├── package.json
│ ├── public
│ │ ├── _headers
│ │ ├── _routes.json
│ │ └── favicon.ico
│ ├── remix.config.js
│ ├── remix.env.d.ts
│ ├── server.ts
│ └── tsconfig.json
├── cloudflare-workers
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── README.md
│ ├── app
│ │ ├── entry.client.tsx
│ │ ├── entry.server.tsx
│ │ ├── root.tsx
│ │ └── routes
│ │ │ └── _index.tsx
│ ├── package.json
│ ├── public
│ │ └── favicon.ico
│ ├── remix.config.js
│ ├── remix.env.d.ts
│ ├── server.ts
│ ├── tsconfig.json
│ └── wrangler.toml
├── deno
│ ├── .gitignore
│ ├── .vscode
│ │ ├── extensions.json
│ │ ├── resolve_npm_imports.json
│ │ └── settings.json
│ ├── README.md
│ ├── app
│ │ ├── entry.client.tsx
│ │ ├── entry.server.tsx
│ │ ├── root.tsx
│ │ └── routes
│ │ │ └── _index.tsx
│ ├── deno.json
│ ├── package.json
│ ├── public
│ │ └── favicon.ico
│ ├── remix.config.js
│ └── server.ts
├── express
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── README.md
│ ├── app
│ │ ├── entry.client.tsx
│ │ ├── entry.server.tsx
│ │ ├── root.tsx
│ │ └── routes
│ │ │ └── _index.tsx
│ ├── package.json
│ ├── public
│ │ └── favicon.ico
│ ├── remix.config.js
│ ├── remix.env.d.ts
│ ├── server.js
│ └── tsconfig.json
├── fly
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── README.md
│ ├── app
│ │ ├── entry.client.tsx
│ │ ├── entry.server.tsx
│ │ ├── root.tsx
│ │ └── routes
│ │ │ └── _index.tsx
│ ├── package.json
│ ├── public
│ │ └── favicon.ico
│ ├── remix.config.js
│ ├── remix.env.d.ts
│ └── tsconfig.json
├── remix-javascript
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── README.md
│ ├── app
│ │ ├── entry.client.jsx
│ │ ├── entry.server.jsx
│ │ ├── root.jsx
│ │ └── routes
│ │ │ └── _index.jsx
│ ├── package.json
│ ├── public
│ │ └── favicon.ico
│ └── remix.config.js
└── remix
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── README.md
│ ├── app
│ ├── entry.client.tsx
│ ├── entry.server.tsx
│ ├── root.tsx
│ └── routes
│ │ └── _index.tsx
│ ├── package.json
│ ├── public
│ └── favicon.ico
│ ├── remix.config.js
│ ├── remix.env.d.ts
│ └── tsconfig.json
├── cloudflare-workers
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── app
│ ├── entry.client.tsx
│ ├── entry.server.tsx
│ ├── root.tsx
│ ├── routes
│ │ └── _index.tsx
│ └── tailwind.css
├── load-context.ts
├── package.json
├── postcss.config.js
├── public
│ ├── favicon.ico
│ ├── logo-dark.png
│ └── logo-light.png
├── server.ts
├── tailwind.config.ts
├── tsconfig.json
├── vite.config.ts
├── worker-configuration.d.ts
└── wrangler.toml
├── cloudflare
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── app
│ ├── entry.client.tsx
│ ├── entry.server.tsx
│ ├── root.tsx
│ ├── routes
│ │ └── _index.tsx
│ └── tailwind.css
├── functions
│ └── [[path]].ts
├── load-context.ts
├── package.json
├── postcss.config.js
├── public
│ ├── _headers
│ ├── _routes.json
│ ├── favicon.ico
│ ├── logo-dark.png
│ └── logo-light.png
├── tailwind.config.ts
├── tsconfig.json
└── vite.config.ts
├── express
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── app
│ ├── entry.client.tsx
│ ├── entry.server.tsx
│ ├── root.tsx
│ ├── routes
│ │ └── _index.tsx
│ └── tailwind.css
├── package.json
├── postcss.config.js
├── public
│ ├── favicon.ico
│ ├── logo-dark.png
│ └── logo-light.png
├── server.js
├── tailwind.config.ts
├── tsconfig.json
└── vite.config.ts
├── remix-javascript
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── app
│ ├── entry.client.jsx
│ ├── entry.server.jsx
│ ├── root.jsx
│ ├── routes
│ │ └── _index.jsx
│ └── tailwind.css
├── package.json
├── postcss.config.js
├── public
│ ├── favicon.ico
│ ├── logo-dark.png
│ └── logo-light.png
├── tailwind.config.js
└── vite.config.js
├── remix-tutorial
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── app
│ ├── app.css
│ ├── data.ts
│ └── root.tsx
├── package.json
├── public
│ └── favicon.ico
├── tsconfig.json
└── vite.config.ts
├── remix
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── app
│ ├── entry.client.tsx
│ ├── entry.server.tsx
│ ├── root.tsx
│ ├── routes
│ │ └── _index.tsx
│ └── tailwind.css
├── package.json
├── postcss.config.js
├── public
│ ├── favicon.ico
│ ├── logo-dark.png
│ └── logo-light.png
├── tailwind.config.ts
├── tsconfig.json
└── vite.config.ts
└── spa
├── .eslintrc.cjs
├── .gitignore
├── README.md
├── app
├── entry.client.tsx
├── root.tsx
├── routes
│ └── _index.tsx
└── tailwind.css
├── package.json
├── postcss.config.js
├── public
├── favicon.ico
├── logo-dark.png
└── logo-light.png
├── tailwind.config.ts
├── tsconfig.json
└── vite.config.ts
/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 |
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 |
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
9 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/build/
2 | **/tests/__snapshots/
3 | **/node_modules/
4 | .tmp
5 | pnpm-lock.yaml
6 | /playground
7 | **/__tests__/fixtures
8 | **/__tests__/**/*/fixtures
9 | /packages/*/dist/
10 |
11 | # Deno
12 | integration/helpers/deno-template
13 | packages/remix-deno
14 | templates/deno
15 |
16 | packages/remix-dev/config/defaults
17 | templates/remix-tutorial/app/data.ts
18 | templates/cloudflare-workers/worker-configuration.d.ts
19 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: github-actions
4 | directory: /
5 | schedule:
6 | interval: daily
7 |
--------------------------------------------------------------------------------
/.github/workflows/merged-pr.yml:
--------------------------------------------------------------------------------
1 | name: 📦 Merged PR
2 |
3 | on:
4 | pull_request:
5 | types: [closed]
6 | branches:
7 | - dev
8 | paths:
9 | - "packages/**"
10 |
11 | permissions:
12 | pull-requests: write
13 |
14 | jobs:
15 | merged:
16 | name: Add label to merged PR
17 | if: github.event.pull_request.merged == true && github.repository == 'remix-run/remix'
18 | runs-on: ubuntu-latest
19 | steps:
20 | - uses: actions/github-script@v7
21 | with:
22 | retries: 3
23 | script: |
24 | await github.rest.issues.addLabels({
25 | owner: context.repo.owner,
26 | repo: context.repo.repo,
27 | issue_number: context.issue.number,
28 | labels: ['awaiting release'],
29 | })
30 |
--------------------------------------------------------------------------------
/.github/workflows/release-comments.yml:
--------------------------------------------------------------------------------
1 | name: 📝 Comment on Release
2 |
3 | on:
4 | workflow_call:
5 |
6 | jobs:
7 | comment:
8 | name: 📝 Comment on related issues and pull requests
9 | if: github.repository == 'remix-run/remix'
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: ⬇️ Checkout repo
13 | uses: actions/checkout@v4
14 | with:
15 | fetch-depth: 0
16 |
17 | - name: 📝 Comment on related issues and pull requests
18 | uses: remix-run/release-comment-action@v0.4.1
19 | with:
20 | DIRECTORY_TO_CHECK: "./packages"
21 | PACKAGE_NAME: "remix"
22 | PR_LABELS_TO_REMOVE: "awaiting release"
23 |
--------------------------------------------------------------------------------
/.github/workflows/website.yml:
--------------------------------------------------------------------------------
1 | name: 🌐 Website
2 |
3 | on:
4 | schedule:
5 | # every hour
6 | - cron: "0 * * * *"
7 | push:
8 | branches: [main, dev]
9 | paths: [docs/**]
10 | release:
11 | types: [published]
12 |
13 | jobs:
14 | website:
15 | if: github.repository == 'remix-run/remix'
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 | - name: 🔄 Refresh the docs
20 | uses: fjogeleit/http-request-action@v1
21 | with:
22 | url: "${{ secrets.DOCS_REFRESH_URL }}?ref=${{ github.ref }}"
23 | method: "POST"
24 | customHeaders: '{"Authorization": "${{ secrets.DOCS_REFRESH_TOKEN }}"}'
25 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 | shell-emulator=true
3 | enable-pre-post-scripts=true
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 18
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .changeset/*.md
2 | pnpm-lock.yaml
3 |
--------------------------------------------------------------------------------
/.vscode/README.md:
--------------------------------------------------------------------------------
1 | A note on `deno_resolve_npm_imports.json`
2 |
3 | The `"imports"` field in `deno_resolve_npm_imports.json` is used to resolve NPM imports for `packages/remix-deno`. This import map is used solely for the d`enoland.vscode-deno` extension.
4 |
5 | Remix does not support import maps. Dependency management is done through `npm` and `node_modules/` instead. Deno-only dependencies may be imported via URL imports (without using import maps).
6 |
--------------------------------------------------------------------------------
/.vscode/deno_resolve_npm_imports.json:
--------------------------------------------------------------------------------
1 | {
2 | "imports": {
3 | "@remix-run/server-runtime": "https://esm.sh/@remix-run/server-runtime@nightly",
4 | "mime": "https://esm.sh/mime@^3.0.0"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "denoland.vscode-deno",
5 | "esbenp.prettier-vscode"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "node_modules/typescript/lib",
3 | "deno.enablePaths": ["./packages/remix-deno/"],
4 | "deno.importMap": "./.vscode/deno_resolve_npm_imports.json"
5 | }
6 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Please see [our guide to contributing](docs/guides/contributing.md).
4 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [
4 | "@babel/preset-env",
5 | {
6 | targets: {
7 | node: "18",
8 | },
9 | },
10 | ],
11 | "@babel/preset-react",
12 | "@babel/preset-typescript",
13 | ],
14 | plugins: [
15 | "@babel/plugin-proposal-export-namespace-from",
16 | "@babel/plugin-proposal-optional-chaining",
17 | // Strip console.debug calls unless REMIX_DEBUG=true
18 | ...(process.env.REMIX_DEBUG === "true"
19 | ? []
20 | : [
21 | [
22 | "transform-remove-console",
23 | { exclude: ["error", "warn", "log", "info"] },
24 | ],
25 | ]),
26 | ],
27 | };
28 |
--------------------------------------------------------------------------------
/decisions/template.md:
--------------------------------------------------------------------------------
1 | # Title
2 |
3 | Date: YYYY-MM-DD
4 |
5 | Status: proposed | rejected | accepted | deprecated | … | superseded by [0005](0005-example.md)
6 |
7 | ## Context
8 |
9 | ## Decision
10 |
11 | ## Consequences
12 |
--------------------------------------------------------------------------------
/docs/components/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Components
3 | order: 5
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/components/links.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Links
3 | toc: false
4 | ---
5 |
6 | # ``
7 |
8 | The `` component renders all of the [``][link_element] tags created by your route module [`links`][links] export. You should render it inside the [`
`][head_element] of your HTML, usually in `app/root.tsx`.
9 |
10 | ```tsx filename=app/root.tsx lines=[7]
11 | import { Links } from "@remix-run/react";
12 |
13 | export default function Root() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 | );
22 | }
23 | ```
24 |
25 | [link_element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link
26 | [head_element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head
27 | [links]: ../route/links
28 |
--------------------------------------------------------------------------------
/docs/components/meta.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Meta
3 | toc: false
4 | ---
5 |
6 | # ``
7 |
8 | This component renders all of the [``][meta_element] tags created by your route module [`meta`][meta] export. You should render it inside the [``][head_element] of your HTML, usually in `app/root.tsx`.
9 |
10 | ```tsx filename=app/root.tsx lines=[7]
11 | import { Meta } from "@remix-run/react";
12 |
13 | export default function Root() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 | );
22 | }
23 | ```
24 |
25 | [meta_element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
26 | [head_element]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head
27 | [meta]: ../route/meta
28 |
--------------------------------------------------------------------------------
/docs/components/outlet.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Outlet
3 | ---
4 |
5 | # ``
6 |
7 | Renders the matching child route of a parent route.
8 |
9 | ```tsx
10 | import { Outlet } from "@remix-run/react";
11 |
12 | export default function SomeParent() {
13 | return (
14 |
15 |
Parent Content
16 |
17 |
18 |
19 | );
20 | }
21 | ```
22 |
23 | ## Props
24 |
25 | ### `context`
26 |
27 | Provides a context value to the element tree below the outlet. Use when the parent route needs to provide values to child routes.
28 |
29 | ```tsx
30 |
31 | ```
32 |
33 | See also: [`useOutletContext`][use-outlet-context]
34 |
35 | [use-outlet-context]: ../hooks/use-outlet-context
36 |
--------------------------------------------------------------------------------
/docs/components/prefetch-page-links.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: PrefetchPageLinks
3 | toc: false
4 | ---
5 |
6 | # ``
7 |
8 | This component enables prefetching of all assets for a page to enable an instant navigation to that page. It does this by rendering `` and `` tags for all the assets (data, modules, css) of a given page.
9 |
10 | `` uses this internally, but you can render it to prefetch a page for any other reason.
11 |
12 | ```tsx
13 |
14 | ```
15 |
16 | **Note:** You need to use an absolute path.
17 |
--------------------------------------------------------------------------------
/docs/discussion/component-data.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Component Data
3 | hidden: true
4 | ---
5 |
6 | # Component Data
7 |
--------------------------------------------------------------------------------
/docs/discussion/cookies-and-sessions.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Cookies and Sessions
3 | hidden: true
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/discussion/error-handling.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Error Handling
3 | hidden: true
4 | ---
5 |
6 | # Error Handling
7 |
8 | - unexpected
9 | - automatically handled
10 | - granular w/ route boundaries
11 | - granular w/ `` boundaries
12 | - expected
13 | - 404s
14 | - 401s
15 | - 503s
16 | - can send data!
17 |
--------------------------------------------------------------------------------
/docs/discussion/form-validation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Form Validation
3 | hidden: true
4 | ---
5 |
6 | # Form Validation
7 |
--------------------------------------------------------------------------------
/docs/discussion/formdata.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Working with FormData
3 | hidden: true
4 | ---
5 |
6 | # Working with FormData
7 |
--------------------------------------------------------------------------------
/docs/discussion/html-forms.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: HTML Form APIs
3 | hidden: true
4 | ---
5 |
6 | # HTML Form APIs
7 |
--------------------------------------------------------------------------------
/docs/discussion/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Discussion Topics
3 | order: 2
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/discussion/multiple-forms.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Multiple Forms on a Page
3 | hidden: true
4 | ---
5 |
6 | # Multiple Forms on a Page
7 |
--------------------------------------------------------------------------------
/docs/discussion/nested-routes.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Layouts and Nested Routes
3 | hidden: true
4 | ---
5 |
6 | # Layouts and Nested Routes
7 |
--------------------------------------------------------------------------------
/docs/discussion/testing.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Testing
3 | hidden: true
4 | ---
5 |
6 | # Testing
7 |
--------------------------------------------------------------------------------
/docs/file-conventions/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: File Conventions
3 | order: 3
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/guides/authentication.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Authentication
3 | hidden: true
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/guides/concurrent-submissions.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Concurrent Submissions
3 | hidden: true
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/guides/debugging.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Debugging
3 | hidden: true
4 | ---
5 |
6 | TODO
7 |
--------------------------------------------------------------------------------
/docs/guides/images.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Handling Images
3 | hidden: true
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/guides/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Guides
3 | order: 10
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/guides/meta.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: SEO and Meta Tags
3 | hidden: true
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/guides/progressive-enhancement.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Progressive Enhancement
3 | hidden: true
4 | ---
5 |
6 | # Progressive Enhancement
7 |
--------------------------------------------------------------------------------
/docs/hooks/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Hooks
3 | order: 6
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/hooks/use-async-value.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: useAsyncValue
3 | new: true
4 | ---
5 |
6 | # `useAsyncValue`
7 |
8 | Returns the resolved data from the closest [``][await_component] ancestor component.
9 |
10 | ```tsx
11 | function SomeDescendant() {
12 | const value = useAsyncValue();
13 | // ...
14 | }
15 | ```
16 |
17 | ```tsx
18 |
19 |
20 |
21 | ```
22 |
23 | ## Additional Resources
24 |
25 | **Guides**
26 |
27 | - [Streaming][streaming_guide]
28 |
29 | **API**
30 |
31 | - [``][await_component]
32 | - [`useAsyncError`][use_async_error]
33 |
34 | [await_component]: ../components/await
35 | [streaming_guide]: ../guides/streaming
36 | [use_async_error]: ../hooks/use-async-error
37 |
--------------------------------------------------------------------------------
/docs/hooks/use-matches.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: useMatches
3 | toc: false
4 | ---
5 |
6 | # `useMatches`
7 |
8 | Returns the current route matches on the page. This is useful for creating layout abstractions with your current routes.
9 |
10 | ```tsx
11 | function SomeComponent() {
12 | const matches = useMatches();
13 |
14 | // ...
15 | }
16 | ```
17 |
18 | `matches` has the following shape:
19 |
20 | ```ts
21 | [
22 | { id, pathname, data, params, handle }, // root route
23 | { id, pathname, data, params, handle }, // layout route
24 | { id, pathname, data, params, handle }, // child route
25 | // etc.
26 | ];
27 | ```
28 |
29 | ## Additional Resources
30 |
31 | - [Breadcrumbs Guide][breadcrumbs-guide]
32 |
33 | [breadcrumbs-guide]: ../guides/breadcrumbs
34 |
--------------------------------------------------------------------------------
/docs/hooks/use-outlet-context.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: useOutletContext
3 | ---
4 |
5 | # `useOutletContext`
6 |
7 | Convenience API over [React Context][react-context] that returns the context value from the closest parent [``][outlet-context] component.
8 |
9 | ```tsx
10 | import { useOutletContext } from "@remix-run/react";
11 |
12 | function Child() {
13 | const myValue = useOutletContext();
14 | // ...
15 | }
16 | ```
17 |
18 | ## Additional Resources
19 |
20 | - [``][outlet-context]
21 |
22 | [react-context]: https://react.dev/learn/passing-data-deeply-with-context
23 | [outlet-context]: ../components/outlet#context
24 |
--------------------------------------------------------------------------------
/docs/hooks/use-outlet.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: useOutlet
3 | ---
4 |
5 | # `useOutlet`
6 |
7 | Returns the element for the child route at this level of the route hierarchy. This hook is used internally by [``][outlet-component] to render child routes.
8 |
9 | ```tsx
10 | import { useOutlet } from "@remix-run/react";
11 | ```
12 |
13 | [outlet-component]: ../components/outlet
14 |
--------------------------------------------------------------------------------
/docs/hooks/use-params.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: useParams
3 | ---
4 |
5 | # `useParams`
6 |
7 | Returns an object of key/value pairs of the dynamic params from the current URL that were matched by the routes. Child routes inherit all params from their parent routes.
8 |
9 | ```tsx
10 | import { useParams } from "@remix-run/react";
11 |
12 | function SomeComponent() {
13 | const params = useParams();
14 | // ...
15 | }
16 | ```
17 |
18 | Assuming a route like `routes/posts/$postId.tsx` is matched by `/posts/123` then `params.postId` will be `"123"`. Params for [splat routes][splat-routes] are available as `params["*"]`.
19 |
20 | [splat-routes]: ../file-conventions/routes#splat-routes
21 |
--------------------------------------------------------------------------------
/docs/hooks/use-route-error.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: useRouteError
3 | new: true
4 | ---
5 |
6 | # `useRouteError`
7 |
8 | Accesses the error thrown during an [`action`][action], [`loader`][loader], or rendering to be used in an [`ErrorBoundary`][error-boundary].
9 |
10 | ```jsx filename=routes/some-route.tsx
11 | export function ErrorBoundary() {
12 | const error = useRouteError();
13 | return {error.message}
;
14 | }
15 | ```
16 |
17 | ## Additional Resources
18 |
19 | **Guides**
20 |
21 | - [Error Handling Guide][error-handling-guide]
22 |
23 | **API Reference**
24 |
25 | - [`ErrorBoundary`][error-boundary]
26 |
27 | [action]: ../route/action
28 | [loader]: ../route/loader
29 | [error-boundary]: ../route/error-boundary
30 | [error-handling-guide]: ../guides/errors
31 |
--------------------------------------------------------------------------------
/docs/hooks/use-route-loader-data.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: useRouteLoaderData
3 | toc: false
4 | ---
5 |
6 | # `useRouteLoaderData`
7 |
8 | Returns the loader data for a given route by ID.
9 |
10 | ```tsx
11 | import { useRouteLoaderData } from "@remix-run/react";
12 |
13 | function SomeComponent() {
14 | const { user } = useRouteLoaderData("root");
15 | }
16 | ```
17 |
18 | Remix creates the route IDs automatically. They are simply the path of the route file relative to the app folder without the extension.
19 |
20 | | Route Filename | Route ID |
21 | | -------------------------- | -------------------- |
22 | | `app/root.tsx` | `"root"` |
23 | | `app/routes/teams.tsx` | `"routes/teams"` |
24 | | `app/routes/teams.$id.tsx` | `"routes/teams.$id"` |
25 |
--------------------------------------------------------------------------------
/docs/other-api/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Other API
3 | order: 9
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/prettier.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('prettier').Options} */
2 | module.exports = {
3 | ...require("../prettier.config"),
4 | printWidth: 60,
5 | };
6 |
--------------------------------------------------------------------------------
/docs/route/component.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Component
3 | ---
4 |
5 | # Route Component
6 |
7 | The default export of a route module defines the component that will render when the route matches.
8 |
9 | ```tsx filename=app/routes/my-route.tsx
10 | export default function MyRouteComponent() {
11 | return (
12 |
13 |
Look ma!
14 |
I'm still using React after like 8 years.
15 |
16 | );
17 | }
18 | ```
19 |
--------------------------------------------------------------------------------
/docs/route/handle.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: handle
3 | ---
4 |
5 | # `handle`
6 |
7 | Exporting a handle allows you to create application conventions with the [`useMatches`][use-matches] hook. You can put whatever values you want on it:
8 |
9 | ```tsx
10 | export const handle = {
11 | its: "all yours",
12 | };
13 | ```
14 |
15 | This is almost always used in conjunction with `useMatches`. To see what kinds of things you can do with it, refer to [`useMatches`][use-matches] for more information.
16 |
17 | ## Additional Resources
18 |
19 | - [Breadcrumbs Guide][breadcrumbs-guide]
20 | - [`useMatches`][use-matches]
21 |
22 | [use-matches]: ../hooks/use-matches
23 | [breadcrumbs-guide]: ../guides/breadcrumbs
24 |
--------------------------------------------------------------------------------
/docs/route/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Route Module
3 | order: 4
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/start/changelog.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Changelog
3 | ---
4 |
5 | # Changelog
6 |
7 | See the detailed changelog for each release on [GitHub][changelog].
8 |
9 | [changelog]: https://github.com/remix-run/remix/blob/main/CHANGELOG.md
10 |
--------------------------------------------------------------------------------
/docs/start/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Getting Started
3 | order: 1
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/styling/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Styling
3 | order: 7
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/tutorials/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Tutorials
3 | hidden: true
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/utils/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Utilities
3 | order: 6
4 | ---
5 |
--------------------------------------------------------------------------------
/docs/utils/is-route-error-response.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: isRouteErrorResponse
3 | toc: false
4 | ---
5 |
6 | # `isRouteErrorResponse`
7 |
8 | This util is simply a re-export of [React Router's `isRouteErrorResponse`][rr-isrouteerrorresponse].
9 |
10 | [rr-isrouteerrorresponse]: https://reactrouter.com/v6/utils/is-route-error-response
11 |
--------------------------------------------------------------------------------
/docs/utils/replace.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: replace
3 | toc: false
4 | ---
5 |
6 | # `replace`
7 |
8 | This is a small wrapper around [`redirect`][redirect] that will trigger a client-side redirect to the new location using `history.replaceState` instead of `history.pushState`.
9 |
10 | If JavaScript has not loaded, this will behave as a standard document-level redirect and will add a new entry to the history stack.
11 |
12 | Just like [`redirect`][redirect], it accepts a status code or a `ResponseInit` as the second parameter:
13 |
14 | ```ts
15 | replace(path, 301);
16 | replace(path, 303);
17 | ```
18 |
19 | ```ts
20 | replace(path, {
21 | headers: {
22 | "Set-Cookie": await commitSession(session),
23 | },
24 | });
25 | ```
26 |
27 | [redirect]: ./redirect
28 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | Remix examples have moved into a dedicated repository. [See `remix-run/examples`](https://github.com/remix-run/examples) to browse or contribute new example projects!
2 |
--------------------------------------------------------------------------------
/integration/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # integration-tests
2 |
3 | ## 0.0.0
4 |
5 | ### Minor Changes
6 |
7 | - Unstable Vite support for Node-based Remix apps ([#7590](https://github.com/remix-run/remix/pull/7590))
8 |
9 | - `remix build` 👉 `vite build && vite build --ssr`
10 | - `remix dev` 👉 `vite dev`
11 |
12 | Other runtimes (e.g. Deno, Cloudflare) not yet supported.
13 | Custom server (e.g. Express) not yet supported.
14 |
15 | See "Future > Vite" in the Remix Docs for details.
16 |
--------------------------------------------------------------------------------
/integration/assets/toupload.txt:
--------------------------------------------------------------------------------
1 | Hello, World!
--------------------------------------------------------------------------------
/integration/helpers/cf-template/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /dist
6 | /public/build
7 | /.mf
8 | .env
9 |
--------------------------------------------------------------------------------
/integration/helpers/cf-template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/integration/helpers/cf-template/public/favicon.ico
--------------------------------------------------------------------------------
/integration/helpers/cf-template/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | declare module "__STATIC_CONTENT_MANIFEST" {
6 | const manifest: string;
7 | export default manifest;
8 | }
9 |
--------------------------------------------------------------------------------
/integration/helpers/cf-template/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "baseUrl": ".",
15 | "paths": {
16 | "~/*": ["./app/*"]
17 | },
18 |
19 | // Remix takes care of building everything in `remix build`.
20 | "noEmit": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/integration/helpers/cf-template/wrangler.toml:
--------------------------------------------------------------------------------
1 | name = "remix-cloudflare-workers"
2 |
3 | workers_dev = true
4 | main = "./build/index.js"
5 | # https://developers.cloudflare.com/workers/platform/compatibility-dates
6 | compatibility_date = "2023-04-20"
7 |
8 | [site]
9 | bucket = "./public"
10 |
--------------------------------------------------------------------------------
/integration/helpers/cleanup.mjs:
--------------------------------------------------------------------------------
1 | import * as path from "node:path";
2 | import spawn from "cross-spawn";
3 |
4 | if (process.env.CI) {
5 | console.log("Skipping cleanup in CI");
6 | process.exit();
7 | }
8 |
9 | const pathsToRemove = [path.resolve(process.cwd(), ".tmp/integration")];
10 |
11 | for (let pathToRemove of pathsToRemove) {
12 | console.log(`Removing ${path.relative(process.cwd(), pathToRemove)}`);
13 | let childProcess;
14 | if (process.platform === "win32") {
15 | childProcess = spawn("rmdir", ["/s", "/q", pathToRemove], {
16 | stdio: "inherit",
17 | });
18 | } else {
19 | childProcess = spawn("rm", ["-rf", pathToRemove], {
20 | stdio: "inherit",
21 | });
22 | }
23 | childProcess.on("error", (err) => {
24 | console.error(err);
25 | process.exit(1);
26 | });
27 | }
28 |
--------------------------------------------------------------------------------
/integration/helpers/deno-template/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/integration/helpers/deno-template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/integration/helpers/deno-template/public/favicon.ico
--------------------------------------------------------------------------------
/integration/helpers/deno-template/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | module.exports = {
3 | server: "./server.ts",
4 | serverConditions: ["deno", "worker"],
5 | serverDependenciesToBundle: "all",
6 | serverMainFields: ["module", "main"],
7 | serverModuleFormat: "esm",
8 | serverPlatform: "neutral",
9 | // appDirectory: "app",
10 | // assetsBuildDirectory: "public/build",
11 | // publicPath: "/build/",
12 | // serverBuildPath: "build/index.js",
13 |
14 | // !!! Don't adjust this without changing the code that overwrites this
15 | // in createFixtureProject()
16 | ...globalThis.INJECTED_FIXTURE_REMIX_CONFIG,
17 | };
18 |
--------------------------------------------------------------------------------
/integration/helpers/deno-template/server.ts:
--------------------------------------------------------------------------------
1 | import { serve } from "https://deno.land/std@0.128.0/http/server.ts";
2 | import { createRequestHandlerWithStaticFiles } from "@remix-run/deno";
3 | // Import path interpreted by the Remix compiler
4 | import * as build from "@remix-run/dev/server-build";
5 |
6 | const remixHandler = createRequestHandlerWithStaticFiles({
7 | build,
8 | getLoadContext: () => ({}),
9 | });
10 |
11 | const port = Number(Deno.env.get("PORT")) || 8000;
12 | console.log(`Listening on http://localhost:${port}`);
13 | serve(remixHandler, { port });
14 |
--------------------------------------------------------------------------------
/integration/helpers/node-template/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/integration/helpers/node-template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/integration/helpers/node-template/public/favicon.ico
--------------------------------------------------------------------------------
/integration/helpers/node-template/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | // appDirectory: "app",
4 | // assetsBuildDirectory: "public/build",
5 | // publicPath: "/build/",
6 | // serverBuildPath: "build/index.js",
7 |
8 | // !!! Don't adjust this without changing the code that overwrites this
9 | // in createFixtureProject()
10 | ...global.INJECTED_FIXTURE_REMIX_CONFIG,
11 | };
12 |
--------------------------------------------------------------------------------
/integration/helpers/node-template/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/integration/helpers/node-template/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "baseUrl": ".",
15 | "paths": {
16 | "~/*": ["./app/*"]
17 | },
18 |
19 | // Remix takes care of building everything in `remix build`.
20 | "noEmit": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/integration/helpers/vite-5-template/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | .env
6 |
--------------------------------------------------------------------------------
/integration/helpers/vite-5-template/app/root.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Links,
3 | Meta,
4 | Outlet,
5 | Scripts,
6 | ScrollRestoration,
7 | } from "@remix-run/react";
8 |
9 | export default function App() {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/integration/helpers/vite-5-template/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/integration/helpers/vite-5-template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/integration/helpers/vite-5-template/public/favicon.ico
--------------------------------------------------------------------------------
/integration/helpers/vite-5-template/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "module": "ESNext",
9 | "moduleResolution": "Bundler",
10 | "resolveJsonModule": true,
11 | "target": "ES2022",
12 | "strict": true,
13 | "allowJs": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 | "noEmit": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/integration/helpers/vite-5-template/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig } from "vite";
3 | import tsconfigPaths from "vite-tsconfig-paths";
4 |
5 | export default defineConfig({
6 | plugins: [remix(), tsconfigPaths()],
7 | });
8 |
--------------------------------------------------------------------------------
/integration/helpers/vite-6-template/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | .env
6 |
--------------------------------------------------------------------------------
/integration/helpers/vite-6-template/app/root.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Links,
3 | Meta,
4 | Outlet,
5 | Scripts,
6 | ScrollRestoration,
7 | } from "@remix-run/react";
8 |
9 | export default function App() {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/integration/helpers/vite-6-template/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/integration/helpers/vite-6-template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/integration/helpers/vite-6-template/public/favicon.ico
--------------------------------------------------------------------------------
/integration/helpers/vite-6-template/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "module": "ESNext",
9 | "moduleResolution": "Bundler",
10 | "resolveJsonModule": true,
11 | "target": "ES2022",
12 | "strict": true,
13 | "allowJs": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 | "noEmit": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/integration/helpers/vite-6-template/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig } from "vite";
3 | import tsconfigPaths from "vite-tsconfig-paths";
4 |
5 | export default defineConfig({
6 | plugins: [remix(), tsconfigPaths()],
7 | });
8 |
--------------------------------------------------------------------------------
/integration/helpers/vite-cloudflare-template/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | .env
6 |
--------------------------------------------------------------------------------
/integration/helpers/vite-cloudflare-template/app/root.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Links,
3 | Meta,
4 | Outlet,
5 | Scripts,
6 | ScrollRestoration,
7 | } from "@remix-run/react";
8 |
9 | export default function App() {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/integration/helpers/vite-cloudflare-template/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/integration/helpers/vite-cloudflare-template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/integration/helpers/vite-cloudflare-template/public/favicon.ico
--------------------------------------------------------------------------------
/integration/helpers/vite-cloudflare-template/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "module": "ESNext",
9 | "moduleResolution": "Bundler",
10 | "resolveJsonModule": true,
11 | "target": "ES2022",
12 | "strict": true,
13 | "allowJs": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 | "noEmit": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/integration/helpers/vite-cloudflare-template/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig } from "vite";
3 | import tsconfigPaths from "vite-tsconfig-paths";
4 |
5 | export default defineConfig({
6 | plugins: [remix(), tsconfigPaths()],
7 | });
8 |
--------------------------------------------------------------------------------
/integration/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["helpers/*-template"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "moduleResolution": "Bundler",
11 | "allowSyntheticDefaultImports": true,
12 | "strict": true,
13 | "resolveJsonModule": true,
14 |
15 | "noEmit": true,
16 |
17 | "rootDir": "."
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/jest/buildRemix.js:
--------------------------------------------------------------------------------
1 | import * as path from "node:path";
2 | import { spawn } from "cross-spawn";
3 |
4 | function buildRemix(dir) {
5 | return new Promise((accept, reject) => {
6 | spawn("pnpm", ["build"], {
7 | stdio: "inherit",
8 | cwd: dir,
9 | })
10 | .on("error", reject)
11 | .on("close", accept);
12 | });
13 | }
14 |
15 | export default async function () {
16 | let rootDir = path.dirname(__dirname);
17 | await buildRemix(rootDir);
18 | }
19 |
--------------------------------------------------------------------------------
/jest/transform.js:
--------------------------------------------------------------------------------
1 | let { default: babelJest } = require("babel-jest");
2 |
3 | let baseConfig = require("../babel.config.js");
4 |
5 | /**
6 | * Replace `import.meta` with `undefined`
7 | *
8 | * Needed to support server-side CJS in Jest
9 | * that access `@remix-run/react`, where `import.meta.hot`
10 | * is used for HMR.
11 | */
12 | let metaPlugin = ({ types: t }) => ({
13 | visitor: {
14 | MetaProperty: (path) => {
15 | path.replaceWith(t.identifier("undefined"));
16 | },
17 | },
18 | });
19 |
20 | module.exports = babelJest.createTransformer({
21 | babelrc: false,
22 | ...baseConfig,
23 | plugins: [...baseConfig.plugins, metaPlugin],
24 | });
25 |
--------------------------------------------------------------------------------
/packages/ADDING_A_PACKAGE.md:
--------------------------------------------------------------------------------
1 | # How to add a package
2 |
3 | - [ ] add folder and make sure it's a unique "name" field in `package.json`
4 | - [ ] add to root package.json `packages` array
5 | - [ ] update rollup config to build the package
6 | - [ ] add root `tsconfig.json` entry and make sure pkg tsconfig is proper output dir
7 | - [ ] add to publish scripts
8 | - [ ] update version script
9 | - [ ] update `.changeset/config.json` to include the package
10 |
--------------------------------------------------------------------------------
/packages/create-remix/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: "../../.eslintrc.js",
3 | rules: {
4 | // we have an example where we need this
5 | "no-undef": 0,
6 | },
7 | overrides: [
8 | {
9 | files: ["rollup.config.js"],
10 | rules: {
11 | "no-undef": 2,
12 | },
13 | },
14 | ],
15 | };
16 |
--------------------------------------------------------------------------------
/packages/create-remix/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/arc.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/create-remix/__tests__/fixtures/arc.tar.gz
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/arc.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/create-remix/__tests__/fixtures/arc.tgz
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/blank/package.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/examples-main.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/create-remix/__tests__/fixtures/examples-main.tar.gz
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/failing-remix-init/package.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/failing-remix-init/remix.init/index.js:
--------------------------------------------------------------------------------
1 | module.exports = () => {
2 | throw new Error("💣");
3 | };
4 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/nested-dir-repo.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/create-remix/__tests__/fixtures/nested-dir-repo.tar.gz
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/remix-repo.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/create-remix/__tests__/fixtures/remix-repo.tar.gz
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/create-remix/__tests__/fixtures/stack.tar.gz
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | - [Remix Docs](https://remix.run/docs)
4 |
5 | ## Development
6 |
7 | From your terminal:
8 |
9 | ```sh
10 | npm run dev
11 | ```
12 |
13 | This starts your app in development mode, rebuilding assets on file changes.
14 |
15 | ## Deployment
16 |
17 | First, build your app for production:
18 |
19 | ```sh
20 | npm run build
21 | ```
22 |
23 | Then run the app in production mode:
24 |
25 | ```sh
26 | npm start
27 | ```
28 |
29 | Now you'll need to pick a host to deploy it to.
30 |
31 | ### DIY
32 |
33 | If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
34 |
35 | Make sure to deploy the output of `remix build`
36 |
37 | - `build/`
38 | - `public/build/`
39 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | import { RemixBrowser } from "@remix-run/react";
2 | import { hydrate } from "react-dom";
3 |
4 | hydrate(, document);
5 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/app/entry.server.tsx:
--------------------------------------------------------------------------------
1 | import type { EntryContext } from "@remix-run/node";
2 | import { RemixServer } from "@remix-run/react";
3 | import { renderToString } from "react-dom/server";
4 |
5 | export default function handleRequest(
6 | request: Request,
7 | responseStatusCode: number,
8 | responseHeaders: Headers,
9 | remixContext: EntryContext
10 | ) {
11 | // eslint-disable-next-line testing-library/render-result-naming-convention
12 | let markup = renderToString(
13 |
14 | );
15 |
16 | responseHeaders.set("Content-Type", "text/html");
17 |
18 | return new Response("" + markup, {
19 | status: responseStatusCode,
20 | headers: responseHeaders,
21 | });
22 | }
23 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/app/root.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Links,
3 | LiveReload,
4 | Meta,
5 | Outlet,
6 | Scripts,
7 | ScrollRestoration,
8 | } from "@remix-run/react";
9 |
10 | export default function App() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/app/utils.ts:
--------------------------------------------------------------------------------
1 | // this is a utility file
2 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "remix-template-remix",
3 | "private": true,
4 | "sideEffects": false,
5 | "scripts": {
6 | "build": "remix build",
7 | "dev": "remix dev",
8 | "start": "remix-serve build/index.js"
9 | },
10 | "dependencies": {
11 | "@remix-run/react": "*",
12 | "not-remix": "*",
13 | "remix": "*"
14 | },
15 | "devDependencies": {},
16 | "engines": {
17 | "node": ">=18.0.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/create-remix/__tests__/fixtures/stack/public/favicon.ico
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | module.exports = {
3 | serverBuildTarget: "node-cjs",
4 | // appDirectory: "app",
5 | // assetsBuildDirectory: "public/build",
6 | // serverBuildPath: "build/index.js",
7 | // publicPath: "/build/",
8 | };
9 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/remix.init/index.js:
--------------------------------------------------------------------------------
1 | // this is the init file
2 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/stack/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "forceConsistentCasingInFileNames": true,
6 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
7 | "isolatedModules": true,
8 | "esModuleInterop": true,
9 | "jsx": "react-jsx",
10 | "moduleResolution": "Bundler",
11 | "resolveJsonModule": true,
12 | "target": "ES2022",
13 | "strict": true,
14 | "baseUrl": ".",
15 | "paths": {
16 | "~/*": ["./app/*"]
17 | },
18 |
19 | // Remix takes care of building everything in `remix build`.
20 | "noEmit": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/successful-remix-init/package.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/successful-remix-init/remix.init/index.js:
--------------------------------------------------------------------------------
1 | const fs = require("node:fs");
2 | const path = require("node:path");
3 |
4 | module.exports = ({ rootDirectory }) => {
5 | fs.writeFileSync(
6 | path.join(rootDirectory, "test.txt"),
7 | "added via remix.init"
8 | );
9 | };
10 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/tar.js:
--------------------------------------------------------------------------------
1 | const tar = require("tar-fs");
2 | const fs = require("node:fs");
3 | const path = require("node:path");
4 |
5 | let files = fs.readdirSync(__dirname);
6 | let dirs = files.filter((file) =>
7 | fs.statSync(path.join(__dirname, file)).isDirectory()
8 | );
9 |
10 | for (let dir of dirs) {
11 | let fullPath = path.join(__dirname, dir);
12 | console.log(`Creating archive for ${fullPath}`);
13 | tar
14 | .pack(fullPath, {
15 | map(header) {
16 | header.name = dir + "/" + header.name;
17 | return header;
18 | },
19 | })
20 | .pipe(fs.createWriteStream(path.join(__dirname, `${dir}.tar.gz`)));
21 | }
22 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/fixtures/with-ignored-dir/package.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/msw-register.ts:
--------------------------------------------------------------------------------
1 | import process from "node:process";
2 |
3 | import { server } from "./msw";
4 |
5 | server.listen({ onUnhandledRequest: "error" });
6 |
7 | process.on("exit", () => {
8 | server.close();
9 | });
10 |
--------------------------------------------------------------------------------
/packages/create-remix/__tests__/setupAfterEnv.ts:
--------------------------------------------------------------------------------
1 | export let jestTimeout = process.platform === "win32" ? 20_000 : 10_000;
2 |
3 | jest.setTimeout(jestTimeout);
4 |
--------------------------------------------------------------------------------
/packages/create-remix/cli.ts:
--------------------------------------------------------------------------------
1 | import process from "node:process";
2 |
3 | import { createRemix } from "./index";
4 |
5 | process.on("SIGINT", () => process.exit(0));
6 | process.on("SIGTERM", () => process.exit(0));
7 |
8 | let argv = process.argv.slice(2).filter((arg) => arg !== "--");
9 |
10 | createRemix(argv).then(
11 | () => process.exit(0),
12 | () => process.exit(1)
13 | );
14 |
--------------------------------------------------------------------------------
/packages/create-remix/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "create-remix",
5 | setupFilesAfterEnv: ["/__tests__/setupAfterEnv.ts"],
6 | setupFiles: [],
7 | };
8 |
--------------------------------------------------------------------------------
/packages/create-remix/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts", "./package.json"],
3 | "exclude": ["dist", "**/node_modules/**", "__tests__"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "moduleResolution": "Bundler",
11 | "allowSyntheticDefaultImports": true,
12 | "strict": true,
13 | "resolveJsonModule": true,
14 | "declaration": true,
15 | "emitDeclarationOnly": true,
16 | "rootDir": ".",
17 | "outDir": "../../build/node_modules/create-remix/dist"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix-architect/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-architect/__tests__/554828.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-architect/__tests__/554828.jpeg
--------------------------------------------------------------------------------
/packages/remix-architect/__tests__/binaryTypes-test.ts:
--------------------------------------------------------------------------------
1 | import { isBinaryType } from "../binaryTypes";
2 |
3 | describe("architect isBinaryType", () => {
4 | it("should detect binary contentType correctly", () => {
5 | expect(isBinaryType(undefined)).toBe(false);
6 | expect(isBinaryType(null)).toBe(false);
7 | expect(isBinaryType("text/html; charset=utf-8")).toBe(false);
8 | expect(isBinaryType("application/octet-stream")).toBe(true);
9 | expect(isBinaryType("application/octet-stream; charset=test")).toBe(true);
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/packages/remix-architect/__tests__/setup.ts:
--------------------------------------------------------------------------------
1 | import { installGlobals } from "@remix-run/node";
2 | installGlobals({ nativeFetch: true });
3 |
--------------------------------------------------------------------------------
/packages/remix-architect/index.ts:
--------------------------------------------------------------------------------
1 | export { createArcTableSessionStorage } from "./sessions/arcTableSessionStorage";
2 |
3 | export type { GetLoadContextFunction, RequestHandler } from "./server";
4 | export { createRequestHandler } from "./server";
5 |
--------------------------------------------------------------------------------
/packages/remix-architect/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "architect",
5 | };
6 |
--------------------------------------------------------------------------------
/packages/remix-architect/rollup.config.js:
--------------------------------------------------------------------------------
1 | const { getAdapterConfig } = require("../../rollup.utils");
2 |
3 | /** @returns {import("rollup").RollupOptions[]} */
4 | module.exports = function rollup() {
5 | return [getAdapterConfig("architect")];
6 | };
7 |
--------------------------------------------------------------------------------
/packages/remix-architect/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "skipLibCheck": true,
8 |
9 | "moduleResolution": "Bundler",
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "declaration": true,
13 | "emitDeclarationOnly": true,
14 | "rootDir": ".",
15 | "outDir": "../../build/node_modules/@remix-run/architect/dist"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare-pages/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare-pages/index.ts:
--------------------------------------------------------------------------------
1 | export type {
2 | createPagesFunctionHandlerParams,
3 | GetLoadContextFunction,
4 | RequestHandler,
5 | } from "./worker";
6 | export { createPagesFunctionHandler, createRequestHandler } from "./worker";
7 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare-pages/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["ES2022"],
6 | "target": "ES2022",
7 | "types": ["@cloudflare/workers-types"],
8 |
9 | "moduleResolution": "Bundler",
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "declaration": true,
13 | "emitDeclarationOnly": true,
14 | "rootDir": ".",
15 | "outDir": "../../build/node_modules/@remix-run/cloudflare-pages/dist",
16 |
17 | // Avoid naming conflicts between history and react-router-dom relying on
18 | // lib.dom.d.ts Window and this being a WebWorker env.
19 | "skipLibCheck": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare-workers/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare-workers/index.ts:
--------------------------------------------------------------------------------
1 | export type { GetLoadContextFunction, RequestHandler } from "./worker";
2 | export {
3 | createEventHandler,
4 | createRequestHandler,
5 | handleAsset,
6 | } from "./worker";
7 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare-workers/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["ES2022"],
6 | "target": "ES2022",
7 | "types": ["@cloudflare/workers-types"],
8 |
9 | "moduleResolution": "Bundler",
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "declaration": true,
13 | "emitDeclarationOnly": true,
14 | "rootDir": ".",
15 | "outDir": "../../build/node_modules/@remix-run/cloudflare-workers/dist",
16 |
17 | // Avoid naming conflicts between history and react-router-dom relying on
18 | // lib.dom.d.ts Window and this being a WebWorker env.
19 | "skipLibCheck": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare/globals.ts:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/a/59499895
2 | export {};
3 |
4 | declare global {
5 | interface ProcessEnv {
6 | NODE_ENV: "development" | "production" | "test";
7 | }
8 |
9 | interface WorkerGlobalScope {
10 | process: { env: ProcessEnv };
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare/implementations.ts:
--------------------------------------------------------------------------------
1 | import {
2 | createCookieFactory,
3 | createCookieSessionStorageFactory,
4 | createMemorySessionStorageFactory,
5 | createSessionStorageFactory,
6 | } from "@remix-run/server-runtime";
7 |
8 | import { sign, unsign } from "./crypto";
9 |
10 | export const createCookie = createCookieFactory({ sign, unsign });
11 | export const createCookieSessionStorage =
12 | createCookieSessionStorageFactory(createCookie);
13 | export const createSessionStorage = createSessionStorageFactory(createCookie);
14 | export const createMemorySessionStorage =
15 | createMemorySessionStorageFactory(createSessionStorage);
16 |
--------------------------------------------------------------------------------
/packages/remix-cloudflare/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["ES2022"],
6 | "target": "ES2022",
7 | "types": ["@cloudflare/workers-types"],
8 |
9 | "moduleResolution": "Bundler",
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "declaration": true,
13 | "emitDeclarationOnly": true,
14 | "rootDir": ".",
15 | "outDir": "../../build/node_modules/@remix-run/cloudflare/dist",
16 |
17 | // Avoid naming conflicts between history and react-router-dom relying on
18 | // lib.dom.d.ts Window and this being a WebWorker env.
19 | "skipLibCheck": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/remix-css-bundle/README.md:
--------------------------------------------------------------------------------
1 | # @remix-run/css-bundle
2 |
3 | This package provides access to the `href` of the generated CSS file when using CSS bundling features in [Remix](https://remix.run).
4 |
5 | ```sh
6 | npm install @remix-run/css-bundle
7 | ```
8 |
9 | For more, see the [Remix docs](https://remix.run/docs).
10 |
--------------------------------------------------------------------------------
/packages/remix-css-bundle/index.ts:
--------------------------------------------------------------------------------
1 | // This file's contents are replaced by `cssBundlePlugin`. This file only exists
2 | // to provide type definitions and a graceful fallback when importing this
3 | // package outside of the Remix compiler.
4 | export const cssBundleHref: string | undefined = undefined;
5 |
--------------------------------------------------------------------------------
/packages/remix-css-bundle/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@remix-run/css-bundle",
3 | "version": "2.16.7",
4 | "description": "CSS bundle href when using CSS bundling features in Remix",
5 | "homepage": "https://remix.run",
6 | "bugs": {
7 | "url": "https://github.com/remix-run/remix/issues"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/remix-run/remix",
12 | "directory": "packages/remix-css-bundle"
13 | },
14 | "license": "MIT",
15 | "main": "./dist/index.js",
16 | "module": "./dist/esm/index.js",
17 | "typings": "./dist/index.d.ts",
18 | "scripts": {
19 | "tsc": "tsc"
20 | },
21 | "engines": {
22 | "node": ">=18.0.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/remix-css-bundle/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "moduleResolution": "Bundler",
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "declaration": true,
12 | "emitDeclarationOnly": true,
13 | "skipLibCheck": true,
14 | "resolveJsonModule": true,
15 | "outDir": "../../build/node_modules/@remix-run/css-bundle/dist",
16 | "rootDir": "."
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/remix-deno/.empty.js:
--------------------------------------------------------------------------------
1 | /*
2 | Intentionally left empty as a dummy input for Rollup.
3 |
4 | This package should not be bundled by Rollup as its source
5 | code is a Deno module, not an NPM package.
6 | */
7 |
--------------------------------------------------------------------------------
/packages/remix-deno/README.md:
--------------------------------------------------------------------------------
1 | # @remix-run/deno
2 |
3 | This package contains a Deno module that provides abstractions for Remix.
4 |
5 | For more, see the [Remix docs](https://remix.run/docs).
6 |
7 | ## Install
8 |
9 | Installation is done via `npm`, but the code itself is Deno source code. Read
10 | more about
11 | [why we use `npm` to manage dependencies for Deno projects](https://github.com/remix-run/remix/blob/main/decisions/0001-use-npm-to-manage-npm-dependencies-for-deno-projects.md)
12 | in Remix.
13 |
14 | ```sh
15 | npm install @remix-run/deno
16 | ```
17 |
--------------------------------------------------------------------------------
/packages/remix-deno/globals.ts:
--------------------------------------------------------------------------------
1 | /*
2 | Remix provides `process.env.NODE_ENV` at compile time.
3 | Declare types for `process` here so that they are available in Deno.
4 | */
5 |
6 | interface ProcessEnv {
7 | NODE_ENV: "development" | "production" | "test";
8 | }
9 | interface Process {
10 | env: ProcessEnv;
11 | }
12 | // deno-lint-ignore no-unused-vars no-var
13 | var process: Process;
14 |
--------------------------------------------------------------------------------
/packages/remix-deno/implementations.ts:
--------------------------------------------------------------------------------
1 | import {
2 | createCookieFactory,
3 | createCookieSessionStorageFactory,
4 | createMemorySessionStorageFactory,
5 | createSessionStorageFactory,
6 | } from "@remix-run/server-runtime";
7 |
8 | import { sign, unsign } from "./crypto.ts";
9 |
10 | export const createCookie = createCookieFactory({ sign, unsign });
11 | export const createCookieSessionStorage = createCookieSessionStorageFactory(
12 | createCookie,
13 | );
14 | export const createSessionStorage = createSessionStorageFactory(createCookie);
15 | export const createMemorySessionStorage = createMemorySessionStorageFactory(
16 | createSessionStorage,
17 | );
18 |
--------------------------------------------------------------------------------
/packages/remix-dev/.gitignore:
--------------------------------------------------------------------------------
1 | server-build.js
2 | server-build.d.ts
3 |
--------------------------------------------------------------------------------
/packages/remix-dev/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /functions/\[\[path\]\].js
5 | /functions/\[\[path\]\].js.map
6 | /public/build
7 | .dev.vars
8 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/.node-version:
--------------------------------------------------------------------------------
1 | 16.13.0
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/public/_headers:
--------------------------------------------------------------------------------
1 | /favicon.ico
2 | Cache-Control: public, max-age=3600, s-maxage=3600
3 | /build/*
4 | Cache-Control: public, max-age=31536000, immutable
5 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/public/_routes.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "include": ["/*"],
4 | "exclude": ["/favicon.ico", "/build/*"]
5 | }
6 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-dev/__tests__/fixtures/cloudflare/public/favicon.ico
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | server: "./server.ts",
4 | serverBuildPath: "functions/[[path]].js",
5 | serverConditions: ["workerd", "worker", "browser"],
6 | serverDependenciesToBundle: "all",
7 | serverMainFields: ["browser", "module", "main"],
8 | serverMinify: true,
9 | serverModuleFormat: "esm",
10 | serverPlatform: "neutral",
11 | // appDirectory: "app",
12 | // assetsBuildDirectory: "public/build",
13 | // publicPath: "/build/",
14 | };
15 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/server.ts:
--------------------------------------------------------------------------------
1 | import { logDevReady } from "@remix-run/cloudflare";
2 | import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
3 | import * as build from "@remix-run/dev/server-build";
4 |
5 | if (process.env.NODE_ENV === "development") {
6 | logDevReady(build);
7 | }
8 |
9 | export const onRequest = createPagesFunctionHandler({ build });
10 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/cloudflare/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "baseUrl": ".",
15 | "paths": {
16 | "~/*": ["./app/*"]
17 | },
18 |
19 | // Remix takes care of building everything in `remix build`.
20 | "noEmit": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/deno/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/deno/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["denoland.vscode-deno"]
3 | }
4 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/deno/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "deno.enable": true,
3 | "deno.lint": true
4 | }
5 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/deno/deno.json:
--------------------------------------------------------------------------------
1 | {
2 | "importMap": ".vscode/resolve_npm_imports.json",
3 | "compilerOptions": {
4 | "lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/deno/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-dev/__tests__/fixtures/deno/public/favicon.ico
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/deno/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | module.exports = {
3 | server: "./server.ts",
4 | serverConditions: ["deno", "worker"],
5 | serverDependenciesToBundle: "all",
6 | serverMainFields: ["module", "main"],
7 | serverModuleFormat: "esm",
8 | serverPlatform: "neutral",
9 | // appDirectory: "app",
10 | // assetsBuildDirectory: "public/build",
11 | // publicPath: "/build/",
12 | // serverBuildPath: "build/index.js",
13 | };
14 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/deno/server.ts:
--------------------------------------------------------------------------------
1 | import { serve } from "https://deno.land/std@0.128.0/http/server.ts";
2 | import { createRequestHandlerWithStaticFiles } from "@remix-run/deno";
3 | // Import path interpreted by the Remix compiler
4 | import * as build from "@remix-run/dev/server-build";
5 |
6 | const remixHandler = createRequestHandlerWithStaticFiles({
7 | build,
8 | getLoadContext: () => ({}),
9 | });
10 |
11 | const port = Number(Deno.env.get("PORT")) || 8000;
12 | console.log(`Listening on http://localhost:${port}`);
13 | serve(remixHandler, { port });
14 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/examples-main.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-dev/__tests__/fixtures/examples-main.tar.gz
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/failing-remix-init/package.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/failing-remix-init/remix.init/index.js:
--------------------------------------------------------------------------------
1 | module.exports = () => {
2 | throw new Error("💣");
3 | };
4 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/nested-dir-repo.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-dev/__tests__/fixtures/nested-dir-repo.tar.gz
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/node/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/node/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | - [Remix Docs](https://remix.run/docs)
4 |
5 | ## Development
6 |
7 | From your terminal:
8 |
9 | ```sh
10 | npm run dev
11 | ```
12 |
13 | This starts your app in development mode, rebuilding assets on file changes.
14 |
15 | ## Deployment
16 |
17 | First, build your app for production:
18 |
19 | ```sh
20 | npm run build
21 | ```
22 |
23 | Then run the app in production mode:
24 |
25 | ```sh
26 | npm start
27 | ```
28 |
29 | Now you'll need to pick a host to deploy it to.
30 |
31 | ### DIY
32 |
33 | If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
34 |
35 | Make sure to deploy the output of `remix build`
36 |
37 | - `build/`
38 | - `public/build/`
39 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/node/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "sideEffects": false,
4 | "type": "module",
5 | "scripts": {
6 | "build": "remix build",
7 | "dev": "remix dev",
8 | "start": "remix-serve build/index.js",
9 | "typecheck": "tsc"
10 | },
11 | "dependencies": {
12 | "@remix-run/css-bundle": "*",
13 | "@remix-run/node": "*",
14 | "@remix-run/react": "*",
15 | "@remix-run/serve": "*",
16 | "isbot": "^4.1.0",
17 | "react": "^18.2.0",
18 | "react-dom": "^18.2.0"
19 | },
20 | "devDependencies": {
21 | "@remix-run/dev": "*",
22 | "@types/react": "^18.2.20",
23 | "@types/react-dom": "^18.2.7",
24 | "eslint": "^8.38.0",
25 | "typescript": "^5.1.6"
26 | },
27 | "engines": {
28 | "node": ">=18.0.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/node/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-dev/__tests__/fixtures/node/public/favicon.ico
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/node/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | // appDirectory: "app",
4 | // assetsBuildDirectory: "public/build",
5 | // publicPath: "/build/",
6 | // serverBuildPath: "build/index.js",
7 | };
8 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/node/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/node/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "baseUrl": ".",
15 | "paths": {
16 | "~/*": ["./app/*"]
17 | },
18 |
19 | // Remix takes care of building everything in `remix build`.
20 | "noEmit": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/remix-repo.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-dev/__tests__/fixtures/remix-repo.tar.gz
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-dev/__tests__/fixtures/stack.tar.gz
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | - [Remix Docs](https://remix.run/docs)
4 |
5 | ## Development
6 |
7 | From your terminal:
8 |
9 | ```sh
10 | npm run dev
11 | ```
12 |
13 | This starts your app in development mode, rebuilding assets on file changes.
14 |
15 | ## Deployment
16 |
17 | First, build your app for production:
18 |
19 | ```sh
20 | npm run build
21 | ```
22 |
23 | Then run the app in production mode:
24 |
25 | ```sh
26 | npm start
27 | ```
28 |
29 | Now you'll need to pick a host to deploy it to.
30 |
31 | ### DIY
32 |
33 | If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
34 |
35 | Make sure to deploy the output of `remix build`
36 |
37 | - `build/`
38 | - `public/build/`
39 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | import { RemixBrowser } from "@remix-run/react";
2 | import { hydrate } from "react-dom";
3 |
4 | hydrate(, document);
5 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/app/root.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Links,
3 | LiveReload,
4 | Meta,
5 | Outlet,
6 | Scripts,
7 | ScrollRestoration,
8 | } from "@remix-run/react";
9 |
10 | export default function App() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/app/utils.ts:
--------------------------------------------------------------------------------
1 | // this is a utility file
2 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "remix-template-remix",
3 | "private": true,
4 | "sideEffects": false,
5 | "scripts": {
6 | "build": "remix build",
7 | "dev": "remix dev",
8 | "start": "remix-serve build/index.js"
9 | },
10 | "dependencies": {},
11 | "devDependencies": {},
12 | "engines": {
13 | "node": ">=18.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/packages/remix-dev/__tests__/fixtures/stack/public/favicon.ico
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | module.exports = {
3 | // appDirectory: "app",
4 | // assetsBuildDirectory: "public/build",
5 | // serverBuildPath: "build/index.js",
6 | // publicPath: "/build/",
7 | };
8 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/remix.init/index.js:
--------------------------------------------------------------------------------
1 | // this is the init file
2 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/stack/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "forceConsistentCasingInFileNames": true,
6 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
7 | "isolatedModules": true,
8 | "esModuleInterop": true,
9 | "jsx": "react-jsx",
10 | "moduleResolution": "Bundler",
11 | "resolveJsonModule": true,
12 | "target": "ES2022",
13 | "strict": true,
14 | "baseUrl": ".",
15 | "paths": {
16 | "~/*": ["./app/*"]
17 | },
18 |
19 | // Remix takes care of building everything in `remix build`.
20 | "noEmit": true
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/successful-remix-init/package.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/successful-remix-init/remix.init/index.js:
--------------------------------------------------------------------------------
1 | const fs = require("node:fs");
2 | const path = require("node:path");
3 |
4 | module.exports = ({ rootDirectory }) => {
5 | fs.writeFileSync(
6 | path.join(rootDirectory, "test.txt"),
7 | "added via remix.init"
8 | );
9 | };
10 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/fixtures/tar.js:
--------------------------------------------------------------------------------
1 | const tar = require("tar-fs");
2 | const fs = require("node:fs");
3 | const path = require("node:path");
4 |
5 | let files = fs.readdirSync(__dirname);
6 | let dirs = files.filter((file) =>
7 | fs.statSync(path.join(__dirname, file)).isDirectory()
8 | );
9 |
10 | for (let dir of dirs) {
11 | let fullPath = path.join(__dirname, dir);
12 | console.log(`Creating archive for ${fullPath}`);
13 | tar
14 | .pack(fullPath, {
15 | map(header) {
16 | header.name = dir + "/" + header.name;
17 | return header;
18 | },
19 | })
20 | .pipe(fs.createWriteStream(path.join(__dirname, `${dir}.tar.gz`)));
21 | }
22 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/setupAfterEnv.ts:
--------------------------------------------------------------------------------
1 | export let jestTimeout = process.platform === "win32" ? 20_000 : 10_000;
2 |
3 | jest.setTimeout(jestTimeout);
4 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/utils/captureError.ts:
--------------------------------------------------------------------------------
1 | class NoErrorThrownError extends Error {}
2 |
3 | export default async (
4 | erroring: Promise | (() => Promise)
5 | ) => {
6 | try {
7 | let promise = typeof erroring === "function" ? erroring() : erroring;
8 | await promise;
9 | throw new NoErrorThrownError();
10 | } catch (error: unknown) {
11 | if (error instanceof NoErrorThrownError) throw error;
12 | return error;
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/utils/eol.ts:
--------------------------------------------------------------------------------
1 | export const normalize = (text: string, normalized = "\n") =>
2 | text.replace(/\r?\n/g, normalized);
3 |
--------------------------------------------------------------------------------
/packages/remix-dev/__tests__/utils/git.ts:
--------------------------------------------------------------------------------
1 | import execa from "execa";
2 |
3 | export const initialCommit = async (projectDir: string) => {
4 | let run = (cmd: string, args: string[]) =>
5 | execa(cmd, args, { cwd: projectDir });
6 | let commands = [
7 | ["init"],
8 |
9 | ["config", "user.name", '"github-actions[bot]"'],
10 | ["config", "user.email", '"github-actions[bot]@users.noreply.github.com"'],
11 |
12 | ["add", "."],
13 | ["commit", "--message", '"initial commit"'],
14 | ];
15 | for (let command of commands) {
16 | await run("git", command);
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/packages/remix-dev/assets-manifest.d.ts:
--------------------------------------------------------------------------------
1 | import type { AssetsManifest } from "@remix-run/dev";
2 |
3 | declare const manifest: AssetsManifest;
4 |
5 | export type { AssetsManifest };
6 | export default manifest;
7 |
--------------------------------------------------------------------------------
/packages/remix-dev/cache.ts:
--------------------------------------------------------------------------------
1 | import { put, get } from "cacache";
2 |
3 | export const putJson = async (cachePath: string, key: string, data: any) =>
4 | put(cachePath, key, JSON.stringify(data));
5 |
6 | export const getJson = async (cachePath: string, key: string) =>
7 | get(cachePath, key).then((obj) => JSON.parse(obj.data.toString("utf-8")));
8 |
--------------------------------------------------------------------------------
/packages/remix-dev/cli.ts:
--------------------------------------------------------------------------------
1 | import { cli } from "./index";
2 |
3 | cli.run().then(
4 | () => {
5 | process.exit(0);
6 | },
7 | (error: unknown) => {
8 | if (error) console.error(error);
9 | process.exit(1);
10 | }
11 | );
12 |
--------------------------------------------------------------------------------
/packages/remix-dev/cli/index.ts:
--------------------------------------------------------------------------------
1 | export { run } from "./run";
2 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/analysis.ts:
--------------------------------------------------------------------------------
1 | import fs from "fs-extra";
2 | import path from "node:path";
3 | import type { Metafile } from "esbuild";
4 |
5 | import type { Context } from "./context";
6 |
7 | export let writeMetafile = (
8 | ctx: Context,
9 | filename: string,
10 | metafile: Metafile
11 | ) => {
12 | let buildDir = path.dirname(ctx.config.serverBuildPath);
13 | fs.outputFileSync(path.join(buildDir, filename), JSON.stringify(metafile));
14 | };
15 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/build.ts:
--------------------------------------------------------------------------------
1 | import * as Compiler from "./compiler";
2 | import type { Context } from "./context";
3 |
4 | export async function build(ctx: Context): Promise {
5 | let compiler = await Compiler.create(ctx);
6 | await compiler.compile();
7 | }
8 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/cancel.ts:
--------------------------------------------------------------------------------
1 | export const CANCEL_PREFIX = "remix-compile-cancel";
2 |
3 | export class Cancel extends Error {
4 | constructor(message: string) {
5 | super(`${CANCEL_PREFIX}: ${message}`);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/context.ts:
--------------------------------------------------------------------------------
1 | import type { RemixConfig } from "../config";
2 | import type { Logger } from "../tux";
3 | import type { FileWatchCache } from "./fileWatchCache";
4 | import type { Options } from "./options";
5 |
6 | export type Context = {
7 | config: RemixConfig;
8 | options: Options;
9 | fileWatchCache: FileWatchCache;
10 | logger: Logger;
11 | };
12 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/css/index.ts:
--------------------------------------------------------------------------------
1 | export { create as createCompiler } from "./compiler";
2 | export { write as writeBundle } from "./bundle";
3 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/index.ts:
--------------------------------------------------------------------------------
1 | export { build } from "./build";
2 | export { type WatchOptions, watch } from "./watch";
3 |
4 | export { type Options as CompileOptions } from "./options";
5 | export { logThrown } from "./utils/log";
6 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/js/index.ts:
--------------------------------------------------------------------------------
1 | export { create as createCompiler } from "./compiler";
2 | export { write } from "./write";
3 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/js/write.ts:
--------------------------------------------------------------------------------
1 | import * as path from "node:path";
2 | import type { OutputFile } from "esbuild";
3 | import fse from "fs-extra";
4 |
5 | import type { RemixConfig } from "../../config";
6 |
7 | export async function write(config: RemixConfig, outputFiles: OutputFile[]) {
8 | await fse.ensureDir(path.dirname(config.assetsBuildDirectory));
9 |
10 | for (let file of outputFiles) {
11 | await fse.ensureDir(path.dirname(file.path));
12 | await fse.writeFile(file.path, file.contents);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/options.ts:
--------------------------------------------------------------------------------
1 | type Mode = "development" | "production" | "test";
2 |
3 | export type Options = {
4 | mode: Mode | Omit;
5 | sourcemap: boolean;
6 |
7 | REMIX_DEV_ORIGIN?: URL; // TODO: required in v2
8 | };
9 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/plugins/absoluteCssUrlsPlugin.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import type { Plugin, PluginBuild } from "esbuild";
3 |
4 | /**
5 | * This plugin treats absolute paths in 'url()' css rules as external to prevent
6 | * breaking changes
7 | */
8 | export const absoluteCssUrlsPlugin = (): Plugin => {
9 | return {
10 | name: "absolute-css-urls-plugin",
11 | setup: async (build: PluginBuild) => {
12 | build.onResolve({ filter: /.*/ }, async (args) => {
13 | let { kind, path: resolvePath } = args;
14 | if (kind === "url-token" && path.isAbsolute(resolvePath)) {
15 | return {
16 | path: resolvePath,
17 | external: true,
18 | };
19 | }
20 | });
21 | },
22 | };
23 | };
24 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/plugins/external.ts:
--------------------------------------------------------------------------------
1 | import type { Plugin } from "esbuild";
2 |
3 | export const externalPlugin = (
4 | filter: RegExp,
5 | options: {
6 | sideEffects?: boolean;
7 | } = {}
8 | ): Plugin => {
9 | return {
10 | name: "external",
11 | setup(build) {
12 | build.onResolve({ filter }, () => {
13 | return { external: true, sideEffects: options.sideEffects };
14 | });
15 | },
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/server/index.ts:
--------------------------------------------------------------------------------
1 | export { create as createCompiler } from "./compiler";
2 | export { write } from "./write";
3 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/server/virtualModules.ts:
--------------------------------------------------------------------------------
1 | interface VirtualModule {
2 | id: string;
3 | filter: RegExp;
4 | }
5 |
6 | export const serverBuildVirtualModule: VirtualModule = {
7 | id: "@remix-run/dev/server-build",
8 | filter: /^@remix-run\/dev\/server-build$/,
9 | };
10 |
11 | export const assetsManifestVirtualModule: VirtualModule = {
12 | id: "@remix-run/dev/assets-manifest",
13 | filter: /^@remix-run\/dev\/assets-manifest$/,
14 | };
15 |
--------------------------------------------------------------------------------
/packages/remix-dev/compiler/utils/crypto.ts:
--------------------------------------------------------------------------------
1 | import * as fs from "node:fs";
2 | import type { BinaryLike } from "node:crypto";
3 | import { createHash } from "node:crypto";
4 |
5 | export function getHash(source: BinaryLike): string {
6 | return createHash("sha256").update(source).digest("hex");
7 | }
8 |
9 | export async function getFileHash(file: string): Promise {
10 | return new Promise((accept, reject) => {
11 | let hash = createHash("sha256");
12 | fs.createReadStream(file)
13 | .on("error", (error) => reject(error))
14 | .on("data", (data) => hash.update(data))
15 | .on("close", () => {
16 | accept(hash.digest("hex"));
17 | });
18 | });
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix-dev/config/defaults/entry.client.tsx:
--------------------------------------------------------------------------------
1 | import { RemixBrowser } from "@remix-run/react";
2 | import { startTransition, StrictMode } from "react";
3 | import { hydrateRoot } from "react-dom/client";
4 |
5 | startTransition(() => {
6 | hydrateRoot(
7 | document,
8 |
9 |
10 |
11 | );
12 | });
13 |
--------------------------------------------------------------------------------
/packages/remix-dev/config/defaults/entry.dev.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | /* eslint-disable */
3 |
4 | export default () => {
5 | import("react");
6 | import("react/jsx-dev-runtime");
7 | import("react/jsx-runtime");
8 | import("react-dom");
9 | import("react-dom/client");
10 | import("react-refresh/runtime");
11 | import("@remix-run/react");
12 | import("remix:hmr");
13 | };
14 |
--------------------------------------------------------------------------------
/packages/remix-dev/config/defaults/entry.server.spa.tsx:
--------------------------------------------------------------------------------
1 | import type { EntryContext } from "@remix-run/node";
2 | import { RemixServer } from "@remix-run/react";
3 | import * as React from "react";
4 | import { renderToString } from "react-dom/server";
5 |
6 | export default function handleRequest(
7 | request: Request,
8 | responseStatusCode: number,
9 | responseHeaders: Headers,
10 | remixContext: EntryContext
11 | ) {
12 | let html = renderToString(
13 |
14 | );
15 | html = "\n" + html;
16 | return new Response(html, {
17 | headers: { "Content-Type": "text/html" },
18 | status: responseStatusCode,
19 | });
20 | }
21 |
--------------------------------------------------------------------------------
/packages/remix-dev/config/serverModes.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * The mode to use when running the server.
3 | */
4 | export enum ServerMode {
5 | Development = "development",
6 | Production = "production",
7 | Test = "test",
8 | }
9 |
10 | export function isValidServerMode(mode: string): mode is ServerMode {
11 | return (
12 | mode === ServerMode.Development ||
13 | mode === ServerMode.Production ||
14 | mode === ServerMode.Test
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/packages/remix-dev/devServer/index.ts:
--------------------------------------------------------------------------------
1 | export { liveReload } from "./liveReload";
2 |
--------------------------------------------------------------------------------
/packages/remix-dev/devServer_unstable/env.ts:
--------------------------------------------------------------------------------
1 | import fse from "fs-extra";
2 | import * as path from "node:path";
3 |
4 | // Import environment variables from: .env, failing gracefully if it doesn't exist
5 | export async function loadEnv(rootDirectory: string): Promise {
6 | let envPath = path.join(rootDirectory, ".env");
7 | if (!fse.existsSync(envPath)) return;
8 |
9 | let result = require("dotenv").config({ path: envPath });
10 | if (result.error) throw result.error;
11 | }
12 |
--------------------------------------------------------------------------------
/packages/remix-dev/invariant.ts:
--------------------------------------------------------------------------------
1 | export default function invariant(
2 | value: boolean,
3 | message?: string
4 | ): asserts value;
5 |
6 | export default function invariant(
7 | value: T | null | undefined,
8 | message?: string
9 | ): asserts value is T;
10 |
11 | export default function invariant(value: any, message?: string) {
12 | if (value === false || value === null || typeof value === "undefined") {
13 | console.error(
14 | "The following error is a bug in Remix; please open an issue! https://github.com/remix-run/remix/issues/new"
15 | );
16 | throw new Error(message);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/remix-dev/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "dev",
5 | setupFilesAfterEnv: ["/__tests__/setupAfterEnv.ts"],
6 | setupFiles: [],
7 | };
8 |
--------------------------------------------------------------------------------
/packages/remix-dev/manifest.ts:
--------------------------------------------------------------------------------
1 | export type Manifest = {
2 | version: string;
3 | url?: string;
4 | entry: {
5 | module: string;
6 | imports: string[];
7 | };
8 | routes: {
9 | [routeId: string]: {
10 | id: string;
11 | parentId?: string;
12 | path?: string;
13 | index?: boolean;
14 | caseSensitive?: boolean;
15 | module: string;
16 | imports?: string[];
17 | hasAction: boolean;
18 | hasLoader: boolean;
19 | hasClientAction: boolean;
20 | hasClientLoader: boolean;
21 | hasErrorBoundary: boolean;
22 | };
23 | };
24 | hmr?: {
25 | timestamp?: number;
26 | runtime: string;
27 | };
28 | };
29 |
--------------------------------------------------------------------------------
/packages/remix-dev/result.ts:
--------------------------------------------------------------------------------
1 | type Ok = { ok: true; value: V };
2 | type Err = { ok: false; error: E };
3 |
4 | export type Result = Ok | Err;
5 |
6 | export let ok = (value: V): Ok => ({ ok: true, value });
7 | export let err = (error: E): Err => ({ ok: false, error });
8 |
--------------------------------------------------------------------------------
/packages/remix-dev/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts", "package.json"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "skipLibCheck": true,
13 | "declaration": true,
14 | "emitDeclarationOnly": true,
15 | "rootDir": ".",
16 | "outDir": "../../build/node_modules/@remix-run/dev/dist"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/remix-dev/tux/format.ts:
--------------------------------------------------------------------------------
1 | import pc from "picocolors";
2 | import type { Formatter } from "picocolors/types";
3 |
4 | type FormatArgs = {
5 | label: string;
6 | color: Formatter;
7 | };
8 |
9 | export let format =
10 | ({ label, color }: FormatArgs) =>
11 | (message: string, details: string[] = []) => {
12 | let lines = [];
13 | lines.push(
14 | (pc.isColorSupported ? pc.inverse(color(` ${label} `)) : `[${label}]`) +
15 | " " +
16 | message
17 | );
18 | if (details.length > 0) {
19 | for (let detail of details) {
20 | lines.push(color("┃") + " " + pc.gray(detail));
21 | }
22 | lines.push(color("┗"));
23 | }
24 | return lines.join("\n");
25 | };
26 |
--------------------------------------------------------------------------------
/packages/remix-dev/tux/index.ts:
--------------------------------------------------------------------------------
1 | export { logger, type Logger } from "./logger";
2 |
--------------------------------------------------------------------------------
/packages/remix-dev/vite/babel.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/consistent-type-imports */
2 | import type { NodePath } from "@babel/traverse";
3 | import type { types as BabelTypes } from "@babel/core";
4 | import { parse } from "@babel/parser";
5 | import * as t from "@babel/types";
6 |
7 | // These `require`s were needed to support building within vite-ecosystem-ci,
8 | // otherwise we get errors that `traverse` and `generate` are not functions.
9 | const traverse = require("@babel/traverse")
10 | .default as typeof import("@babel/traverse").default;
11 | const generate = require("@babel/generator")
12 | .default as typeof import("@babel/generator").default;
13 |
14 | export { traverse, generate, parse, t };
15 | export type { BabelTypes, NodePath };
16 |
--------------------------------------------------------------------------------
/packages/remix-dev/vite/combine-urls.ts:
--------------------------------------------------------------------------------
1 | // Borrowed from axios: https://github.com/axios/axios/blob/0e4f9fa29077ebee4499facea6be1492b42e8a26/lib/helpers/combineURLs.js#L11-L15
2 | export function combineURLs(baseURL: string, relativeURL: string) {
3 | return relativeURL
4 | ? baseURL.replace(/\/+$/, "") + "/" + relativeURL.replace(/^\/+/, "")
5 | : baseURL;
6 | }
7 |
--------------------------------------------------------------------------------
/packages/remix-dev/vite/index.ts:
--------------------------------------------------------------------------------
1 | // This file allows us to dynamically require the plugin so non-Vite consumers
2 | // don't need to have Vite installed as a peer dependency. Only types should
3 | // be imported at the top level, or code that doesn't import Vite.
4 | import type { RemixVitePlugin } from "./plugin";
5 | export type {
6 | BuildManifest,
7 | Preset,
8 | VitePluginConfig,
9 | ServerBundlesFunction,
10 | } from "./plugin";
11 |
12 | export const vitePlugin: RemixVitePlugin = (...args) => {
13 | // eslint-disable-next-line @typescript-eslint/consistent-type-imports
14 | let { remixVitePlugin } = require("./plugin") as typeof import("./plugin");
15 | return remixVitePlugin(...args);
16 | };
17 |
18 | export { cloudflareDevProxyVitePlugin } from "./cloudflare-proxy-plugin";
19 |
--------------------------------------------------------------------------------
/packages/remix-dev/vite/is-in-remix-monorepo.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 |
3 | export function isInRemixMonorepo() {
4 | try {
5 | let devPath = path.dirname(require.resolve("@remix-run/node/package.json"));
6 | let devParentDir = path.basename(path.resolve(devPath, ".."));
7 | return devParentDir === "packages";
8 | } catch {
9 | return false;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/remix-dev/vite/resolve-file-url.ts:
--------------------------------------------------------------------------------
1 | import * as path from "node:path";
2 |
3 | import { getVite } from "./vite";
4 |
5 | export const resolveFileUrl = (
6 | { rootDirectory }: { rootDirectory: string },
7 | filePath: string
8 | ) => {
9 | let vite = getVite();
10 | let relativePath = path.relative(rootDirectory, filePath);
11 | let isWithinRoot =
12 | !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
13 |
14 | if (!isWithinRoot) {
15 | // Vite will prevent serving files outside of the workspace
16 | // unless user explicitly opts in with `server.fs.allow`
17 | // https://vitejs.dev/config/server-options.html#server-fs-allow
18 | return path.posix.join("/@fs", vite.normalizePath(filePath));
19 | }
20 |
21 | return "/" + vite.normalizePath(relativePath);
22 | };
23 |
--------------------------------------------------------------------------------
/packages/remix-dev/vite/ssr-externals.ts:
--------------------------------------------------------------------------------
1 | import { isInRemixMonorepo } from "./is-in-remix-monorepo";
2 |
3 | export const ssrExternals = isInRemixMonorepo()
4 | ? [
5 | // This is only needed within the Remix repo because these
6 | // packages are linked to a directory outside of node_modules
7 | // so Vite treats them as internal code by default.
8 | "@remix-run/architect",
9 | "@remix-run/cloudflare-pages",
10 | "@remix-run/cloudflare-workers",
11 | "@remix-run/cloudflare",
12 | "@remix-run/css-bundle",
13 | "@remix-run/deno",
14 | "@remix-run/dev",
15 | "@remix-run/express",
16 | "@remix-run/netlify",
17 | "@remix-run/node",
18 | "@remix-run/react",
19 | "@remix-run/serve",
20 | "@remix-run/server-runtime",
21 | ]
22 | : undefined;
23 |
--------------------------------------------------------------------------------
/packages/remix-dev/vite/vmod.ts:
--------------------------------------------------------------------------------
1 | export let id = (name: string) => `virtual:remix/${name}`;
2 | export let resolve = (id: string) => `\0${id}`;
3 | export let url = (id: string) => `/@id/__x00__${id}`;
4 |
--------------------------------------------------------------------------------
/packages/remix-eslint-config/node.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @see https://github.com/eslint/eslint/issues/3458
3 | * @see https://www.npmjs.com/package/@rushstack/eslint-patch
4 | */
5 | require("@rushstack/eslint-patch/modern-module-resolution");
6 |
7 | module.exports = {
8 | plugins: ["node"],
9 | env: {
10 | node: true,
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/packages/remix-eslint-config/rules/import.js:
--------------------------------------------------------------------------------
1 | // const OFF = 0;
2 | // const WARN = 1;
3 | const ERROR = 2;
4 |
5 | module.exports = {
6 | "import/first": ERROR,
7 | "import/no-amd": ERROR,
8 | "import/no-duplicates": ERROR,
9 | "import/no-webpack-loader-syntax": ERROR,
10 | };
11 |
--------------------------------------------------------------------------------
/packages/remix-eslint-config/rules/jest-dom.js:
--------------------------------------------------------------------------------
1 | // const OFF = 0;
2 | const WARN = 1;
3 | // const ERROR = 2;
4 |
5 | module.exports = {
6 | "jest-dom/prefer-checked": WARN,
7 | "jest-dom/prefer-empty": WARN,
8 | "jest-dom/prefer-enabled-disabled": WARN,
9 | "jest-dom/prefer-focus": WARN,
10 | "jest-dom/prefer-in-document": WARN,
11 | "jest-dom/prefer-required": WARN,
12 | "jest-dom/prefer-to-have-attribute": WARN,
13 | "jest-dom/prefer-to-have-class": WARN,
14 | "jest-dom/prefer-to-have-style": WARN,
15 | "jest-dom/prefer-to-have-text-content": WARN,
16 | "jest-dom/prefer-to-have-value": WARN,
17 | };
18 |
--------------------------------------------------------------------------------
/packages/remix-eslint-config/rules/jest.js:
--------------------------------------------------------------------------------
1 | // const OFF = 0;
2 | const WARN = 1;
3 | const ERROR = 2;
4 |
5 | module.exports = {
6 | "jest/no-conditional-expect": WARN,
7 | "jest/no-deprecated-functions": WARN,
8 | "jest/no-disabled-tests": WARN,
9 | "jest/no-export": ERROR,
10 | "jest/no-focused-tests": WARN,
11 | "jest/no-identical-title": WARN,
12 | "jest/no-interpolation-in-snapshots": WARN,
13 | "jest/no-jasmine-globals": ERROR,
14 | "jest/no-jest-import": WARN,
15 | "jest/no-mocks-import": WARN,
16 | "jest/valid-describe-callback": ERROR,
17 | "jest/valid-expect": ERROR,
18 | "jest/valid-expect-in-promise": ERROR,
19 | };
20 |
--------------------------------------------------------------------------------
/packages/remix-eslint-config/settings/import.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "import/ignore": ["node_modules", "\\.(css|md|svg|json)$"],
3 | "import/parsers": {
4 | [require.resolve("@typescript-eslint/parser")]: [".ts", ".tsx", ".d.ts"],
5 | },
6 | "import/resolver": {
7 | [require.resolve("eslint-import-resolver-node")]: {
8 | extensions: [".js", ".jsx", ".ts", ".tsx"],
9 | },
10 | [require.resolve("eslint-import-resolver-typescript")]: {
11 | alwaysTryTypes: true,
12 | },
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/packages/remix-eslint-config/settings/react.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | react: {
3 | version: "detect",
4 | formComponents: ["Form"],
5 | linkComponents: [
6 | {
7 | name: "Link",
8 | linkAttribute: "to",
9 | },
10 | {
11 | name: "NavLink",
12 | linkAttribute: "to",
13 | },
14 | ],
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/packages/remix-express/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-express/__tests__/setup.ts:
--------------------------------------------------------------------------------
1 | import { installGlobals } from "@remix-run/node";
2 | installGlobals({ nativeFetch: true });
3 |
--------------------------------------------------------------------------------
/packages/remix-express/index.ts:
--------------------------------------------------------------------------------
1 | export type { GetLoadContextFunction, RequestHandler } from "./server";
2 | export { createRequestHandler } from "./server";
3 |
--------------------------------------------------------------------------------
/packages/remix-express/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "express",
5 | };
6 |
--------------------------------------------------------------------------------
/packages/remix-express/rollup.config.js:
--------------------------------------------------------------------------------
1 | const { getAdapterConfig } = require("../../rollup.utils");
2 |
3 | /** @returns {import("rollup").RollupOptions[]} */
4 | module.exports = function rollup() {
5 | return [getAdapterConfig("express")];
6 | };
7 |
--------------------------------------------------------------------------------
/packages/remix-express/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "skipLibCheck": true,
8 |
9 | "moduleResolution": "Bundler",
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "declaration": true,
13 | "emitDeclarationOnly": true,
14 | "rootDir": ".",
15 | "outDir": "../../build/node_modules/@remix-run/express/dist"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/remix-fs-routes/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-fs-routes/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "moduleResolution": "Bundler",
11 | "allowSyntheticDefaultImports": true,
12 | "strict": true,
13 | "jsx": "react",
14 | "declaration": true,
15 | "emitDeclarationOnly": true,
16 | "rootDir": ".",
17 | "outDir": "../../build/node_modules/@remix-run/fs-routes/dist"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix-node/.gitignore:
--------------------------------------------------------------------------------
1 | # TODO: Remove in v2
2 | globals.d.ts
--------------------------------------------------------------------------------
/packages/remix-node/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-node/__tests__/assets/test.txt:
--------------------------------------------------------------------------------
1 | hello, world!
--------------------------------------------------------------------------------
/packages/remix-node/__tests__/setup.ts:
--------------------------------------------------------------------------------
1 | import { installGlobals } from "@remix-run/node";
2 | installGlobals({ nativeFetch: true });
3 |
--------------------------------------------------------------------------------
/packages/remix-node/__tests__/utils.ts:
--------------------------------------------------------------------------------
1 | import prettier from "prettier";
2 |
3 | export function prettyHtml(source: string): string {
4 | return prettier.format(source, { parser: "html" });
5 | }
6 |
--------------------------------------------------------------------------------
/packages/remix-node/crypto.ts:
--------------------------------------------------------------------------------
1 | import cookieSignature from "cookie-signature";
2 | import type { SignFunction, UnsignFunction } from "@remix-run/server-runtime";
3 |
4 | export const sign: SignFunction = async (value, secret) => {
5 | return cookieSignature.sign(value, secret);
6 | };
7 |
8 | export const unsign: UnsignFunction = async (
9 | signed: string,
10 | secret: string
11 | ) => {
12 | return cookieSignature.unsign(signed, secret);
13 | };
14 |
--------------------------------------------------------------------------------
/packages/remix-node/implementations.ts:
--------------------------------------------------------------------------------
1 | import {
2 | createCookieFactory,
3 | createCookieSessionStorageFactory,
4 | createMemorySessionStorageFactory,
5 | createSessionStorageFactory,
6 | } from "@remix-run/server-runtime";
7 |
8 | import { sign, unsign } from "./crypto";
9 |
10 | export const createCookie = createCookieFactory({ sign, unsign });
11 | export const createCookieSessionStorage =
12 | createCookieSessionStorageFactory(createCookie);
13 | export const createSessionStorage = createSessionStorageFactory(createCookie);
14 | export const createMemorySessionStorage =
15 | createMemorySessionStorageFactory(createSessionStorage);
16 |
--------------------------------------------------------------------------------
/packages/remix-node/install.d.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/packages/remix-node/install.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | "use strict";
3 |
4 | var globals = require("./dist/globals.js");
5 |
6 | Object.defineProperty(exports, "__esModule", { value: true });
7 |
8 | globals.installGlobals();
9 |
--------------------------------------------------------------------------------
/packages/remix-node/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "node",
5 | };
6 |
--------------------------------------------------------------------------------
/packages/remix-node/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 |
9 | "moduleResolution": "Bundler",
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "declaration": true,
13 | "emitDeclarationOnly": true,
14 | "rootDir": ".",
15 | "outDir": "../../build/node_modules/@remix-run/node/dist",
16 |
17 | // Avoid naming conflicts between lib.dom.d.ts and globals.ts
18 | "skipLibCheck": true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/remix-react/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-react/__tests__/setup.ts:
--------------------------------------------------------------------------------
1 | const JSDOMFormData = global.FormData;
2 | global.TextDecoder = require("util").TextDecoder;
3 | global.TextEncoder = require("util").TextEncoder;
4 | global.ReadableStream = require("stream/web").ReadableStream;
5 | global.WritableStream = require("stream/web").WritableStream;
6 |
7 | require("@remix-run/node").installGlobals({ nativeFetch: true });
8 | global.FormData = JSDOMFormData;
9 |
--------------------------------------------------------------------------------
/packages/remix-react/invariant.ts:
--------------------------------------------------------------------------------
1 | export default function invariant(
2 | value: boolean,
3 | message?: string
4 | ): asserts value;
5 | export default function invariant(
6 | value: T | null | undefined,
7 | message?: string
8 | ): asserts value is T;
9 | export default function invariant(value: any, message?: string) {
10 | if (value === false || value === null || typeof value === "undefined") {
11 | throw new Error(message);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/remix-react/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "react",
5 | testEnvironment: "jsdom",
6 | };
7 |
--------------------------------------------------------------------------------
/packages/remix-react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts", "**/*.tsx"],
3 | "exclude": ["future/*.d.ts", "dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "moduleResolution": "Bundler",
11 | "allowSyntheticDefaultImports": true,
12 | "strict": true,
13 | "jsx": "react",
14 | "declaration": true,
15 | "emitDeclarationOnly": true,
16 | "rootDir": ".",
17 | "outDir": "../../build/node_modules/@remix-run/react/dist"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix-react/warnings.ts:
--------------------------------------------------------------------------------
1 | const alreadyWarned: { [message: string]: boolean } = {};
2 |
3 | export function warnOnce(condition: boolean, message: string): void {
4 | if (!condition && !alreadyWarned[message]) {
5 | alreadyWarned[message] = true;
6 | console.warn(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/remix-route-config/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-route-config/index.ts:
--------------------------------------------------------------------------------
1 | export type {
2 | UNSAFE_RouteConfig as RouteConfig,
3 | UNSAFE_RouteConfigEntry as RouteConfigEntry,
4 | } from "@remix-run/dev";
5 |
6 | export {
7 | route,
8 | index,
9 | layout,
10 | prefix,
11 | relative,
12 | getAppDirectory,
13 | } from "./routes";
14 |
--------------------------------------------------------------------------------
/packages/remix-route-config/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "route-config",
5 | setupFiles: [],
6 | };
7 |
--------------------------------------------------------------------------------
/packages/remix-route-config/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "moduleResolution": "Bundler",
11 | "allowSyntheticDefaultImports": true,
12 | "strict": true,
13 | "jsx": "react",
14 | "declaration": true,
15 | "emitDeclarationOnly": true,
16 | "rootDir": ".",
17 | "outDir": "../../build/node_modules/@remix-run/route-config/dist"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix-routes-option-adapter/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-routes-option-adapter/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "moduleResolution": "Bundler",
11 | "allowSyntheticDefaultImports": true,
12 | "strict": true,
13 | "jsx": "react",
14 | "declaration": true,
15 | "emitDeclarationOnly": true,
16 | "rootDir": ".",
17 | "outDir": "../../build/node_modules/@remix-run/routes-option-adapter/dist"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix-serve/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-serve/rollup.config.js:
--------------------------------------------------------------------------------
1 | const { getCliConfig } = require("../../rollup.utils");
2 | const { name: packageName, version } = require("./package.json");
3 |
4 | /** @returns {import("rollup").RollupOptions[]} */
5 | module.exports = function rollup() {
6 | return [getCliConfig({ packageName, version })];
7 | };
8 |
--------------------------------------------------------------------------------
/packages/remix-serve/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "moduleResolution": "Bundler",
11 | "allowSyntheticDefaultImports": true,
12 | "strict": true,
13 | "declaration": true,
14 | "emitDeclarationOnly": true,
15 | "rootDir": ".",
16 | "outDir": "../../build/node_modules/@remix-run/serve/dist"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/.eslintrc.js:
--------------------------------------------------------------------------------
1 | let restrictedGlobalsError = `Node globals are not allowed in this package.`;
2 |
3 | module.exports = {
4 | extends: "../../.eslintrc.js",
5 | rules: {
6 | "no-restricted-globals": [
7 | "error",
8 | { name: "__dirname", message: restrictedGlobalsError },
9 | { name: "__filename", message: restrictedGlobalsError },
10 | { name: "Buffer", message: restrictedGlobalsError },
11 | ],
12 | "import/no-nodejs-modules": "error",
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/__tests__/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /** @type {import('eslint').Linter.Config} */
2 | module.exports = {
3 | rules: {
4 | "no-restricted-globals": "off",
5 | "import/no-nodejs-modules": "off",
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/__tests__/setup.ts:
--------------------------------------------------------------------------------
1 | import { installGlobals } from "@remix-run/node";
2 |
3 | installGlobals({ nativeFetch: true });
4 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/deprecations.ts:
--------------------------------------------------------------------------------
1 | export function resourceRouteJsonWarning(
2 | type: "loader" | "action",
3 | routeId: string
4 | ) {
5 | return (
6 | "⚠️ REMIX FUTURE CHANGE: Externally-accessed resource routes will no longer be " +
7 | "able to return raw JavaScript objects or `null` in React Router v7 when " +
8 | "Single Fetch becomes the default. You can prepare for this change at your " +
9 | `convenience by wrapping the data returned from your \`${type}\` function in ` +
10 | `the \`${routeId}\` route with \`json()\`. For instructions on making this ` +
11 | "change, see https://remix.run/docs/en/v2.13.1/guides/single-fetch#resource-routes"
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/future.ts:
--------------------------------------------------------------------------------
1 | export interface Future {}
2 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/interface.ts:
--------------------------------------------------------------------------------
1 | export type { CreateCookieFunction, IsCookieFunction } from "./cookies";
2 | export type { JsonFunction, RedirectFunction } from "./responses";
3 | export type { CreateRequestHandlerFunction } from "./server";
4 | export type {
5 | CreateSessionFunction,
6 | CreateSessionStorageFunction,
7 | IsSessionFunction,
8 | } from "./sessions";
9 | export type { CreateCookieSessionStorageFunction } from "./sessions/cookieStorage";
10 | export type { CreateMemorySessionStorageFunction } from "./sessions/memoryStorage";
11 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/invariant.ts:
--------------------------------------------------------------------------------
1 | export default function invariant(
2 | value: boolean,
3 | message?: string
4 | ): asserts value;
5 | export default function invariant(
6 | value: T | null | undefined,
7 | message?: string
8 | ): asserts value is T;
9 | export default function invariant(value: any, message?: string) {
10 | if (value === false || value === null || typeof value === "undefined") {
11 | console.error(
12 | "The following error is a bug in Remix; please open an issue! https://github.com/remix-run/remix/issues/new"
13 | );
14 | throw new Error(message);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "server-runtime",
5 | };
6 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/markup.ts:
--------------------------------------------------------------------------------
1 | // This escapeHtml utility is based on https://github.com/zertosh/htmlescape
2 | // License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE
3 |
4 | // We've chosen to inline the utility here to reduce the number of npm dependencies we have,
5 | // slightly decrease the code size compared the original package and make it esm compatible.
6 |
7 | const ESCAPE_LOOKUP: { [match: string]: string } = {
8 | "&": "\\u0026",
9 | ">": "\\u003e",
10 | "<": "\\u003c",
11 | "\u2028": "\\u2028",
12 | "\u2029": "\\u2029",
13 | };
14 |
15 | const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
16 |
17 | export function escapeHtml(html: string) {
18 | return html.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]);
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/mode.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * The mode to use when running the server.
3 | */
4 | export enum ServerMode {
5 | Development = "development",
6 | Production = "production",
7 | Test = "test",
8 | }
9 |
10 | export function isServerMode(value: any): value is ServerMode {
11 | return (
12 | value === ServerMode.Development ||
13 | value === ServerMode.Production ||
14 | value === ServerMode.Test
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 |
8 | "moduleResolution": "Bundler",
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "declaration": true,
12 | "emitDeclarationOnly": true,
13 | "rootDir": ".",
14 | "outDir": "../../build/node_modules/@remix-run/server-runtime/dist",
15 |
16 | // Avoid naming conflicts between lib.dom.d.ts and globals.ts
17 | "skipLibCheck": true
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/typecheck.ts:
--------------------------------------------------------------------------------
1 | // typecheck that expression is assignable to type
2 | export function expectType(_expression: T) {}
3 |
4 | // prettier-ignore
5 | // adapted from https://github.com/type-challenges/type-challenges/blob/main/utils/index.d.ts
6 | export type Equal =
7 | (() => T extends X ? 1 : 2) extends
8 | (() => T extends Y ? 1 : 2) ? true : false
9 |
10 | // adapted from https://github.com/type-challenges/type-challenges/blob/main/utils/index.d.ts
11 | export type Expect = T;
12 |
13 | // looser, lazy equality check for recursive types
14 | // prettier-ignore
15 | export type MutualExtends = [A] extends [B] ? [B] extends [A] ? true : false : false
16 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/upload/errors.ts:
--------------------------------------------------------------------------------
1 | export class MaxPartSizeExceededError extends Error {
2 | constructor(public field: string, public maxBytes: number) {
3 | super(`Field "${field}" exceeded upload size of ${maxBytes} bytes.`);
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/remix-server-runtime/warnings.ts:
--------------------------------------------------------------------------------
1 | const alreadyWarned: { [message: string]: boolean } = {};
2 |
3 | export function warnOnce(condition: boolean, message: string): void {
4 | if (!condition && !alreadyWarned[message]) {
5 | alreadyWarned[message] = true;
6 | console.warn(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/remix-testing/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | [Remix](https://remix.run) is a web framework that helps you build better websites with React.
4 |
5 | To get started, open a new shell and run:
6 |
7 | ```sh
8 | npx create-remix@latest
9 | ```
10 |
11 | Then follow the prompts you see in your terminal.
12 |
13 | For more information about Remix, [visit remix.run](https://remix.run)!
14 |
--------------------------------------------------------------------------------
/packages/remix-testing/index.ts:
--------------------------------------------------------------------------------
1 | export type { RemixStubProps } from "./create-remix-stub";
2 | export { createRemixStub } from "./create-remix-stub";
3 |
--------------------------------------------------------------------------------
/packages/remix-testing/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('jest').Config} */
2 | module.exports = {
3 | ...require("../../jest/jest.config.shared"),
4 | displayName: "testing",
5 | setupFiles: [],
6 | testEnvironment: "jsdom",
7 | setupFilesAfterEnv: ["./jest.setup.js", "@testing-library/jest-dom"],
8 | };
9 |
--------------------------------------------------------------------------------
/packages/remix-testing/jest.setup.js:
--------------------------------------------------------------------------------
1 | const JSDOMFormData = global.FormData;
2 | global.TextDecoder = require("util").TextDecoder;
3 | global.TextEncoder = require("util").TextEncoder;
4 | global.ReadableStream = require("stream/web").ReadableStream;
5 | global.WritableStream = require("stream/web").WritableStream;
6 |
7 | require("@remix-run/node").installGlobals({ nativeFetch: true });
8 | global.FormData = JSDOMFormData;
9 |
--------------------------------------------------------------------------------
/packages/remix-testing/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts", "**/*.tsx"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "moduleResolution": "Bundler",
11 | "allowSyntheticDefaultImports": true,
12 | "strict": true,
13 | "jsx": "react",
14 | "declaration": true,
15 | "emitDeclarationOnly": true,
16 | "rootDir": ".",
17 | "outDir": "../../build/node_modules/@remix-run/testing/dist"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/remix/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # `remix`
2 |
3 | See the `CHANGELOG.md` in individual Remix packages for all changes.
4 |
--------------------------------------------------------------------------------
/packages/remix/index.ts:
--------------------------------------------------------------------------------
1 | // This class exists to prevent https://github.com/remix-run/remix/issues/2031 from occurring
2 | export class RemixPackageNotUsedError extends Error {
3 | constructor() {
4 | super(
5 | "The `remix` package is no longer used for Remix modules and should be removed " +
6 | "from your project dependencies. See " +
7 | "https://github.com/remix-run/remix/releases/tag/remix%402.0.0" +
8 | " for more information."
9 | );
10 | }
11 | }
12 |
13 | throw new RemixPackageNotUsedError();
14 |
--------------------------------------------------------------------------------
/packages/remix/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "remix",
3 | "version": "2.16.7",
4 | "description": "A framework for building better websites",
5 | "homepage": "https://remix.run",
6 | "bugs": {
7 | "url": "https://github.com/remix-run/remix/issues"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/remix-run/remix",
12 | "directory": "packages/remix"
13 | },
14 | "license": "MIT",
15 | "sideEffects": false,
16 | "main": "dist/index.js",
17 | "typings": "dist/index.d.ts",
18 | "module": "dist/esm/index.js",
19 | "scripts": {
20 | "tsc": "tsc"
21 | },
22 | "engines": {
23 | "node": ">=18.0.0"
24 | },
25 | "files": [
26 | "dist/",
27 | "CHANGELOG.md",
28 | "LICENSE.md",
29 | "README.md"
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/packages/remix/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["**/*.ts"],
3 | "exclude": ["dist", "__tests__", "node_modules"],
4 | "compilerOptions": {
5 | "lib": ["ES2022"],
6 | "target": "ES2022",
7 | "module": "ES2022",
8 | "skipLibCheck": true,
9 |
10 | "jsx": "react",
11 | "moduleResolution": "Bundler",
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "declaration": true,
15 | "emitDeclarationOnly": true,
16 | "rootDir": ".",
17 | "outDir": "../../build/node_modules/remix/dist"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/playground/README.md:
--------------------------------------------------------------------------------
1 | # Playground
2 |
3 | This is where you can put Remix projects that use a local version of Remix. Learn more in [the contributing docs](https://remix.run/pages/contributing)
4 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - "integration"
3 | - "integration/helpers/*"
4 | - "packages/*"
5 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('prettier').Options} */
2 | module.exports = {};
3 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | const fs = require("node:fs");
2 | const path = require("node:path");
3 |
4 | module.exports = function rollup(options) {
5 | return fs.readdirSync("packages").flatMap((dir) => {
6 | let configPath = path.join("packages", dir, "rollup.config.js");
7 | try {
8 | fs.readFileSync(configPath);
9 | } catch {
10 | return [];
11 | }
12 | let packageBuild = require(`.${path.sep}${configPath}`);
13 | return packageBuild(options);
14 | });
15 | };
16 |
--------------------------------------------------------------------------------
/scripts/bump-fetch-versions.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | VERSION="${1}"
4 |
5 | if [ "${VERSION}" == "" ]; then
6 | VERSION="latest"
7 | fi
8 |
9 |
10 | echo "Updating the undici dependencies to version '${VERSION}'"
11 | echo ""
12 |
13 | if [ ! -d "packages/remix-node" ]; then
14 | echo "Must be run from the remix repository"
15 | exit 1
16 | fi
17 |
18 | set -x
19 |
20 | cd packages/remix-node
21 | pnpm add undici@${VERSION}
22 | cd ../..
23 |
24 | set +x
--------------------------------------------------------------------------------
/scripts/copy-templates-to-fixtures.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -x
4 |
5 | cp -r templates/cloudflare-pages/* packages/remix-dev/__tests__/fixtures/cloudflare/
6 | rm -f packages/remix-dev/__tests__/fixtures/cloudflare/app/entry.client.tsx
7 | rm -f packages/remix-dev/__tests__/fixtures/cloudflare/app/entry.server.tsx
8 |
9 | cp -r templates/deno/* packages/remix-dev/__tests__/fixtures/deno/
10 | rm -f packages/remix-dev/__tests__/fixtures/deno/app/entry.client.tsx
11 | rm -f packages/remix-dev/__tests__/fixtures/deno/app/entry.server.tsx
12 |
13 | cp -r templates/remix/* packages/remix-dev/__tests__/fixtures/node/
14 | rm -f packages/remix-dev/__tests__/fixtures/node/app/entry.client.tsx
15 | rm -f packages/remix-dev/__tests__/fixtures/node/app/entry.server.tsx
16 |
17 | set +x
18 |
--------------------------------------------------------------------------------
/scripts/deployment-test/cypress.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/scripts/deployment-test/cypress/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parserOptions: {
3 | tsconfigRootDir: __dirname,
4 | project: "./tsconfig.json",
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/scripts/deployment-test/cypress/e2e/smoke.ts:
--------------------------------------------------------------------------------
1 | describe("smoke", () => {
2 | it("should work", () => {
3 | cy.visit("/");
4 | cy.contains("a", "15m Quickstart Blog Tutorial");
5 | });
6 | });
7 |
--------------------------------------------------------------------------------
/scripts/deployment-test/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/scripts/deployment-test/cypress/plugins/index.ts:
--------------------------------------------------------------------------------
1 | module.exports = (
2 | on: Cypress.PluginEvents,
3 | config: Cypress.PluginConfigOptions
4 | ) => {
5 | let configOverrides: Partial = {
6 | viewportWidth: 1030,
7 | viewportHeight: 800,
8 | integrationFolder: "cypress/e2e",
9 | video: !process.env.CI,
10 | screenshotOnRunFailure: !process.env.CI,
11 | };
12 | Object.assign(config, configOverrides);
13 |
14 | on("task", {
15 | log(message) {
16 | console.log(message);
17 | return null;
18 | },
19 | });
20 |
21 | return config;
22 | };
23 |
--------------------------------------------------------------------------------
/scripts/deployment-test/cypress/support/index.js:
--------------------------------------------------------------------------------
1 | import "@testing-library/cypress/add-commands";
2 |
--------------------------------------------------------------------------------
/scripts/deployment-test/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "exclude": [
3 | "../node_modules/@types/jest",
4 | "../node_modules/@testing-library/jest-dom"
5 | ],
6 | "include": [
7 | "./index.ts",
8 | "e2e/**/*",
9 | "plugins/**/*",
10 | "support/**/*",
11 | "../node_modules/cypress",
12 | "../node_modules/@testing-library/cypress"
13 | ],
14 | "compilerOptions": {
15 | "baseUrl": ".",
16 | "noEmit": true,
17 | "types": ["node", "cypress", "@testing-library/cypress"],
18 | "esModuleInterop": true,
19 | "jsx": "react",
20 | "moduleResolution": "Bundler",
21 | "target": "ES2022",
22 | "strict": true,
23 | "skipLibCheck": true,
24 | "resolveJsonModule": true,
25 | "typeRoots": ["../types", "../node_modules/@types"]
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/scripts/deployment-test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "deployment-test",
3 | "description": "deps needed for testing remix deployments",
4 | "private": true,
5 | "scripts": {},
6 | "dependencies": {
7 | "@architect/destroy": "^3.0.3",
8 | "@architect/parser": "^5.0.2",
9 | "@architect/utils": "^3.0.4",
10 | "@aws-sdk/client-apigatewayv2": "^3.310.0",
11 | "@iarna/toml": "^2.2.5",
12 | "@npmcli/package-json": "^4.0.1",
13 | "@testing-library/cypress": "^8.0.2",
14 | "cypress": "^9.2.0",
15 | "fetch-retry": "^5.0.2",
16 | "fs-extra": "^10.0.0",
17 | "semver": "^7.3.7",
18 | "start-server-and-test": "^1.14.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/scripts/playground/template/.env:
--------------------------------------------------------------------------------
1 | DATABASE_URL="file:./data.db?connection_limit=1"
2 | SESSION_SECRET="super-duper-s3cret"
3 |
--------------------------------------------------------------------------------
/scripts/playground/template/.gitignore:
--------------------------------------------------------------------------------
1 | **/public/build
2 |
3 | **/prisma/data.db
4 | **/prisma/data.db-journal
5 |
--------------------------------------------------------------------------------
/scripts/playground/template/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /build
4 | /public/build
5 | .env
6 |
7 | /app/styles/tailwind.css
8 |
--------------------------------------------------------------------------------
/scripts/playground/template/README.md:
--------------------------------------------------------------------------------
1 | # Remix Playground
2 |
3 | This project has everything set up for you to play around with the local Remix packages in a real app environment.
4 |
5 | To create a new project within the `playground` directory (which is ignored by `.gitignore`), execute the command `pnpm playground:new `. For more details, please refer to [the contributing guidelines](https://remix.run/pages/contributing).
6 |
--------------------------------------------------------------------------------
/scripts/playground/template/app/db.server.ts:
--------------------------------------------------------------------------------
1 | import { PrismaClient } from "@prisma/client";
2 |
3 | let prisma: PrismaClient;
4 |
5 | declare global {
6 | // eslint-disable-next-line prefer-let/prefer-let
7 | var __db__: PrismaClient;
8 | }
9 |
10 | // this is needed because in development we don't want to restart
11 | // the server with every change, but we want to make sure we don't
12 | // create a new connection to the DB with every change either.
13 | // in production we'll have a single connection to the DB.
14 | if (process.env.NODE_ENV === "production") {
15 | prisma = new PrismaClient();
16 | } else {
17 | if (!global.__db__) {
18 | global.__db__ = new PrismaClient();
19 | }
20 | prisma = global.__db__;
21 | prisma.$connect();
22 | }
23 |
24 | export { prisma };
25 |
--------------------------------------------------------------------------------
/scripts/playground/template/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | import { RemixBrowser } from "@remix-run/react";
2 | import { startTransition, StrictMode } from "react";
3 | import { hydrateRoot } from "react-dom/client";
4 |
5 | const hydrate = () => {
6 | startTransition(() => {
7 | hydrateRoot(
8 | document,
9 |
10 |
11 |
12 | );
13 | });
14 | };
15 |
16 | if (typeof requestIdleCallback === "function") {
17 | requestIdleCallback(hydrate);
18 | } else {
19 | // Safari doesn't support requestIdleCallback
20 | // https://caniuse.com/requestidlecallback
21 | setTimeout(hydrate, 1);
22 | }
23 |
--------------------------------------------------------------------------------
/scripts/playground/template/app/routes/logout.tsx:
--------------------------------------------------------------------------------
1 | import type { ActionFunctionArgs } from "@remix-run/node";
2 | import { redirect } from "@remix-run/node";
3 |
4 | import { logout } from "~/session.server";
5 |
6 | export async function action({ request }: ActionFunctionArgs) {
7 | return logout(request);
8 | }
9 |
10 | export async function loader() {
11 | return redirect("/");
12 | }
13 |
--------------------------------------------------------------------------------
/scripts/playground/template/app/routes/notes/index.tsx:
--------------------------------------------------------------------------------
1 | import type { MetaFunction } from "@remix-run/node";
2 | import { Link } from "@remix-run/react";
3 |
4 | export const meta: MetaFunction = () => {
5 | return [{ title: "Remix Notes" }];
6 | };
7 |
8 | export default function NoteIndexPage() {
9 | return (
10 |
11 | No note selected. Select a note on the left, or{" "}
12 |
13 | create a new note.
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/scripts/playground/template/app/styles/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/scripts/playground/template/prisma/migrations/migration_lock.toml:
--------------------------------------------------------------------------------
1 | # Please do not edit this file manually
2 | # It should be added in your version-control system (i.e. Git)
3 | provider = "sqlite"
--------------------------------------------------------------------------------
/scripts/playground/template/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/scripts/playground/template/public/favicon.ico
--------------------------------------------------------------------------------
/scripts/playground/template/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | module.exports = {
3 | cacheDirectory: "./node_modules/.cache/remix",
4 | ignoredRouteFiles: ["**/*.css", "**/*.test.{js,jsx,ts,tsx}"],
5 | };
6 |
--------------------------------------------------------------------------------
/scripts/playground/template/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/scripts/playground/template/remix.init/index.js:
--------------------------------------------------------------------------------
1 | const { execSync } = require("node:child_process");
2 |
3 | const main = async ({ rootDirectory }) => {
4 | execSync(`npm run build`, { stdio: "inherit", cwd: rootDirectory });
5 | execSync(`npm run setup`, { stdio: "inherit", cwd: rootDirectory });
6 |
7 | console.log(
8 | `Setup is complete. You're now ready to rock and roll 🤘
9 |
10 | Start development with \`npm run dev\`
11 | `.trim()
12 | );
13 | };
14 |
15 | module.exports = main;
16 |
--------------------------------------------------------------------------------
/scripts/playground/template/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
4 | theme: {
5 | extend: {},
6 | },
7 | plugins: [],
8 | };
9 |
--------------------------------------------------------------------------------
/scripts/playground/template/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "exclude": [],
3 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
4 | "compilerOptions": {
5 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
6 | "types": ["vitest/globals"],
7 | "isolatedModules": true,
8 | "esModuleInterop": true,
9 | "jsx": "react-jsx",
10 | "module": "ES2022",
11 | "moduleResolution": "Bundler",
12 | "resolveJsonModule": true,
13 | "target": "ES2022",
14 | "strict": true,
15 | "allowJs": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "~/*": ["./app/*"]
20 | },
21 | "skipLibCheck": true,
22 |
23 | // Remix takes care of building everything in `remix build`.
24 | "noEmit": true
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/scripts/prompt-confirm.d.ts:
--------------------------------------------------------------------------------
1 | declare module "prompt-confirm" {
2 | class Confirm {
3 | constructor(question: string, answers?: any, rl?: any);
4 | run(): Promise;
5 | }
6 | export = Confirm;
7 | }
8 |
--------------------------------------------------------------------------------
/scripts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["."],
3 | "exclude": ["./deployment-test", "./playground/template/**/*"],
4 | "compilerOptions": {
5 | "allowJs": true,
6 | "checkJs": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "allowSyntheticDefaultImports": true,
9 | "moduleResolution": "Bundler",
10 | "module": "ES2022",
11 | "noEmit": true,
12 | "strict": true,
13 | "target": "ES2022"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/templates/.eslintignore:
--------------------------------------------------------------------------------
1 | deno
2 |
--------------------------------------------------------------------------------
/templates/.gitignore:
--------------------------------------------------------------------------------
1 | package-lock.json
2 | yarn.lock
3 | pnpm-lock.yaml
4 | pnpm-lock.yml
5 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/arc/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /public/build
5 | /server/index.mjs
6 | /server/index.mjs.map
7 | /server/metafile.*
8 | /server/version.txt
9 | preferences.arc
10 | sam.json
11 | sam.yaml
12 | .env
13 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/arc/app.arc:
--------------------------------------------------------------------------------
1 | @app
2 | remix-architect-app
3 |
4 | @aws
5 | runtime nodejs18.x
6 | # concurrency 1
7 | # memory 1152
8 | # profile default
9 | # region us-west-1
10 | # timeout 30
11 |
12 | @http
13 | /*
14 | method any
15 | src server
16 |
17 | @plugins
18 | plugin-remix
19 | src plugin-remix.js
20 |
21 | @static
22 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/arc/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/arc/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/classic-remix-compiler/arc/public/favicon.ico
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/arc/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | ignoredRouteFiles: ["**/*.css"],
4 | publicPath: "/_static/build/",
5 | server: "server.ts",
6 | serverBuildPath: "server/index.mjs",
7 | // appDirectory: "app",
8 | // assetsBuildDirectory: "public/build",
9 | serverModuleFormat: "esm",
10 | };
11 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/arc/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/arc/server.ts:
--------------------------------------------------------------------------------
1 | import { createRequestHandler } from "@remix-run/architect";
2 | import * as build from "@remix-run/dev/server-build";
3 | import { installGlobals } from "@remix-run/node";
4 | import sourceMapSupport from "source-map-support";
5 |
6 | sourceMapSupport.install();
7 | installGlobals({ nativeFetch: true });
8 |
9 | export const handler = createRequestHandler({ build });
10 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/arc/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "skipLibCheck": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 |
20 | // Remix takes care of building everything in `remix build`.
21 | "noEmit": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /functions/\[\[path\]\].js
5 | /functions/\[\[path\]\].js.map
6 | /functions/metafile.*
7 | /functions/version.txt
8 | /public/build
9 | .dev.vars
10 | .wrangler
11 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/.node-version:
--------------------------------------------------------------------------------
1 | 18.0.0
2 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/public/_headers:
--------------------------------------------------------------------------------
1 | /favicon.ico
2 | Cache-Control: public, max-age=3600, s-maxage=3600
3 | /build/*
4 | Cache-Control: public, max-age=31536000, immutable
5 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/public/_routes.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "include": ["/*"],
4 | "exclude": ["/favicon.ico", "/build/*"]
5 | }
6 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/classic-remix-compiler/cloudflare-pages/public/favicon.ico
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | ignoredRouteFiles: ["**/*.css"],
4 | server: "./server.ts",
5 | serverBuildPath: "functions/[[path]].js",
6 | serverConditions: ["workerd", "worker", "browser"],
7 | serverDependenciesToBundle: "all",
8 | serverMainFields: ["browser", "module", "main"],
9 | serverMinify: true,
10 | serverModuleFormat: "esm",
11 | serverPlatform: "neutral",
12 | // appDirectory: "app",
13 | // assetsBuildDirectory: "public/build",
14 | // publicPath: "/build/",
15 | };
16 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/server.ts:
--------------------------------------------------------------------------------
1 | import { logDevReady } from "@remix-run/cloudflare";
2 | import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
3 | import * as build from "@remix-run/dev/server-build";
4 |
5 | if (process.env.NODE_ENV === "development") {
6 | logDevReady(build);
7 | }
8 |
9 | export const onRequest = createPagesFunctionHandler({ build });
10 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-pages/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "skipLibCheck": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 |
20 | // Remix takes care of building everything in `remix build`.
21 | "noEmit": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-workers/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /.wrangler
5 | /build
6 | /public/build
7 | .env
8 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-workers/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-workers/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/classic-remix-compiler/cloudflare-workers/public/favicon.ico
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-workers/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | ignoredRouteFiles: ["**/*.css"],
4 | server: "./server.ts",
5 | serverConditions: ["workerd", "worker", "browser"],
6 | serverDependenciesToBundle: [
7 | // bundle everything except the virtual module for the static content manifest provided by wrangler
8 | /^(?!.*\b__STATIC_CONTENT_MANIFEST\b).*$/,
9 | ],
10 | serverMainFields: ["browser", "module", "main"],
11 | serverMinify: true,
12 | serverModuleFormat: "esm",
13 | serverPlatform: "neutral",
14 | // appDirectory: "app",
15 | // assetsBuildDirectory: "public/build",
16 | // publicPath: "/build/",
17 | // serverBuildPath: "build/index.js",
18 | };
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-workers/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | declare module "__STATIC_CONTENT_MANIFEST" {
6 | const manifest: string;
7 | export default manifest;
8 | }
9 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-workers/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "skipLibCheck": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 |
20 | // Remix takes care of building everything in `remix build`.
21 | "noEmit": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/cloudflare-workers/wrangler.toml:
--------------------------------------------------------------------------------
1 | name = "remix-cloudflare-workers"
2 |
3 | workers_dev = true
4 | main = "./build/index.js"
5 | # https://developers.cloudflare.com/workers/platform/compatibility-dates
6 | compatibility_date = "2023-04-20"
7 |
8 | [site]
9 | bucket = "./public"
10 |
11 | [build]
12 | command = "npm run build"
13 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/deno/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/deno/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["denoland.vscode-deno"]
3 | }
4 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/deno/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "deno.enable": true,
3 | "deno.lint": true
4 | }
5 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/deno/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/deno/deno.json:
--------------------------------------------------------------------------------
1 | {
2 | "importMap": ".vscode/resolve_npm_imports.json",
3 | "compilerOptions": {
4 | "lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/deno/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/classic-remix-compiler/deno/public/favicon.ico
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/deno/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | module.exports = {
3 | ignoredRouteFiles: ["**/*.css"],
4 | server: "./server.ts",
5 | serverConditions: ["deno", "worker"],
6 | serverDependenciesToBundle: "all",
7 | serverMainFields: ["module", "main"],
8 | serverModuleFormat: "esm",
9 | serverPlatform: "neutral",
10 | // appDirectory: "app",
11 | // assetsBuildDirectory: "public/build",
12 | // publicPath: "/build/",
13 | // serverBuildPath: "build/index.js",
14 | };
15 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/deno/server.ts:
--------------------------------------------------------------------------------
1 | import { createRequestHandlerWithStaticFiles } from "@remix-run/deno";
2 | // Import path interpreted by the Remix compiler
3 | import * as build from "@remix-run/dev/server-build";
4 |
5 | const remixHandler = createRequestHandlerWithStaticFiles({
6 | build,
7 | getLoadContext: () => ({}),
8 | });
9 |
10 | const port = Number(Deno.env.get("PORT")) || 8000;
11 | Deno.serve({ port }, remixHandler);
12 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/express/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/express/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/express/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/classic-remix-compiler/express/public/favicon.ico
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/express/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | ignoredRouteFiles: ["**/*.css"],
4 | serverModuleFormat: "esm",
5 | // appDirectory: "app",
6 | // assetsBuildDirectory: "public/build",
7 | // publicPath: "/build/",
8 | // serverBuildPath: "build/index.js",
9 | };
10 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/express/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/express/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "skipLibCheck": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 |
20 | // Remix takes care of building everything in `remix build`.
21 | "noEmit": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/fly/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/fly/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/fly/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/classic-remix-compiler/fly/public/favicon.ico
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/fly/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | ignoredRouteFiles: ["**/*.css"],
4 | // appDirectory: "app",
5 | // assetsBuildDirectory: "public/build",
6 | // publicPath: "/build/",
7 | // serverBuildPath: "build/index.js",
8 | };
9 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/fly/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/fly/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "skipLibCheck": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 |
20 | // Remix takes care of building everything in `remix build`.
21 | "noEmit": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix-javascript/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix-javascript/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | - [Remix Docs](https://remix.run/docs)
4 |
5 | ## Development
6 |
7 | From your terminal:
8 |
9 | ```sh
10 | npm run dev
11 | ```
12 |
13 | This starts your app in development mode, rebuilding assets on file changes.
14 |
15 | ## Deployment
16 |
17 | First, build your app for production:
18 |
19 | ```sh
20 | npm run build
21 | ```
22 |
23 | Then run the app in production mode:
24 |
25 | ```sh
26 | npm start
27 | ```
28 |
29 | Now you'll need to pick a host to deploy it to.
30 |
31 | ### DIY
32 |
33 | If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
34 |
35 | Make sure to deploy the output of `remix build`
36 |
37 | - `build/`
38 | - `public/build/`
39 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix-javascript/app/entry.client.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix-javascript/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/classic-remix-compiler/remix-javascript/public/favicon.ico
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix-javascript/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | ignoredRouteFiles: ["**/*.css"],
4 | // appDirectory: "app",
5 | // assetsBuildDirectory: "public/build",
6 | // publicPath: "/build/",
7 | // serverBuildPath: "build/index.js",
8 | };
9 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | - [Remix Docs](https://remix.run/docs)
4 |
5 | ## Development
6 |
7 | From your terminal:
8 |
9 | ```sh
10 | npm run dev
11 | ```
12 |
13 | This starts your app in development mode, rebuilding assets on file changes.
14 |
15 | ## Deployment
16 |
17 | First, build your app for production:
18 |
19 | ```sh
20 | npm run build
21 | ```
22 |
23 | Then run the app in production mode:
24 |
25 | ```sh
26 | npm start
27 | ```
28 |
29 | Now you'll need to pick a host to deploy it to.
30 |
31 | ### DIY
32 |
33 | If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
34 |
35 | Make sure to deploy the output of `remix build`
36 |
37 | - `build/`
38 | - `public/build/`
39 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/classic-remix-compiler/remix/public/favicon.ico
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix/remix.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('@remix-run/dev').AppConfig} */
2 | export default {
3 | ignoredRouteFiles: ["**/*.css"],
4 | // appDirectory: "app",
5 | // assetsBuildDirectory: "public/build",
6 | // publicPath: "/build/",
7 | // serverBuildPath: "build/index.js",
8 | };
9 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix/remix.env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/templates/classic-remix-compiler/remix/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "isolatedModules": true,
6 | "esModuleInterop": true,
7 | "jsx": "react-jsx",
8 | "moduleResolution": "Bundler",
9 | "resolveJsonModule": true,
10 | "target": "ES2022",
11 | "strict": true,
12 | "allowJs": true,
13 | "skipLibCheck": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "baseUrl": ".",
16 | "paths": {
17 | "~/*": ["./app/*"]
18 | },
19 |
20 | // Remix takes care of building everything in `remix build`.
21 | "noEmit": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/templates/cloudflare-workers/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.wrangler
4 | /build
5 | .env
6 | .dev.vars
7 |
--------------------------------------------------------------------------------
/templates/cloudflare-workers/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/cloudflare-workers/app/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | html,
6 | body {
7 | @apply bg-white dark:bg-gray-950;
8 |
9 | @media (prefers-color-scheme: dark) {
10 | color-scheme: dark;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/cloudflare-workers/load-context.ts:
--------------------------------------------------------------------------------
1 | import { type PlatformProxy } from "wrangler";
2 |
3 | type GetLoadContextArgs = {
4 | request: Request;
5 | context: {
6 | cloudflare: Omit, "dispose" | "caches" | "cf"> & {
7 | caches: PlatformProxy["caches"] | CacheStorage;
8 | cf: Request["cf"];
9 | };
10 | };
11 | };
12 |
13 | declare module "@remix-run/cloudflare" {
14 | // eslint-disable-next-line @typescript-eslint/no-empty-interface
15 | interface AppLoadContext extends ReturnType {
16 | // This will merge the result of `getLoadContext` into the `AppLoadContext`
17 | }
18 | }
19 |
20 | export function getLoadContext({ context }: GetLoadContextArgs) {
21 | return context;
22 | }
23 |
--------------------------------------------------------------------------------
/templates/cloudflare-workers/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/templates/cloudflare-workers/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/cloudflare-workers/public/favicon.ico
--------------------------------------------------------------------------------
/templates/cloudflare-workers/public/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/cloudflare-workers/public/logo-dark.png
--------------------------------------------------------------------------------
/templates/cloudflare-workers/public/logo-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/cloudflare-workers/public/logo-light.png
--------------------------------------------------------------------------------
/templates/cloudflare-workers/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | export default {
4 | content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
5 | theme: {
6 | extend: {
7 | fontFamily: {
8 | sans: [
9 | "Inter",
10 | "ui-sans-serif",
11 | "system-ui",
12 | "sans-serif",
13 | "Apple Color Emoji",
14 | "Segoe UI Emoji",
15 | "Segoe UI Symbol",
16 | "Noto Color Emoji",
17 | ],
18 | },
19 | },
20 | },
21 | plugins: [],
22 | } satisfies Config;
23 |
--------------------------------------------------------------------------------
/templates/cloudflare-workers/worker-configuration.d.ts:
--------------------------------------------------------------------------------
1 | // Generated by Wrangler by running `wrangler types`
2 |
3 | interface Env {}
4 |
--------------------------------------------------------------------------------
/templates/cloudflare-workers/wrangler.toml:
--------------------------------------------------------------------------------
1 | #:schema node_modules/wrangler/config-schema.json
2 | name = "remix-cloudflare-workers-template"
3 |
4 | main = "./server.ts"
5 | workers_dev = true
6 | # https://developers.cloudflare.com/workers/platform/compatibility-dates
7 | compatibility_date = "2024-09-26"
8 |
9 | [assets]
10 | # https://developers.cloudflare.com/workers/static-assets/binding/
11 | directory = "./build/client"
12 |
13 | [build]
14 | command = "npm run build"
15 |
--------------------------------------------------------------------------------
/templates/cloudflare/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | .env
6 | .dev.vars
7 |
8 | .wrangler
9 |
--------------------------------------------------------------------------------
/templates/cloudflare/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/cloudflare/app/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | html,
6 | body {
7 | @apply bg-white dark:bg-gray-950;
8 |
9 | @media (prefers-color-scheme: dark) {
10 | color-scheme: dark;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/cloudflare/functions/[[path]].ts:
--------------------------------------------------------------------------------
1 | import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
2 |
3 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4 | // @ts-ignore - the server build file is generated by `remix vite:build`
5 | // eslint-disable-next-line import/no-unresolved
6 | import * as build from "../build/server";
7 |
8 | export const onRequest = createPagesFunctionHandler({ build });
9 |
--------------------------------------------------------------------------------
/templates/cloudflare/load-context.ts:
--------------------------------------------------------------------------------
1 | import { type PlatformProxy } from "wrangler";
2 |
3 | // When using `wrangler.toml` to configure bindings,
4 | // `wrangler types` will generate types for those bindings
5 | // into the global `Env` interface.
6 | // Need this empty interface so that typechecking passes
7 | // even if no `wrangler.toml` exists.
8 | // eslint-disable-next-line @typescript-eslint/no-empty-interface
9 | interface Env {}
10 |
11 | type Cloudflare = Omit, "dispose">;
12 |
13 | declare module "@remix-run/cloudflare" {
14 | interface AppLoadContext {
15 | cloudflare: Cloudflare;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/templates/cloudflare/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/templates/cloudflare/public/_headers:
--------------------------------------------------------------------------------
1 | /favicon.ico
2 | Cache-Control: public, max-age=3600, s-maxage=3600
3 | /assets/*
4 | Cache-Control: public, max-age=31536000, immutable
5 |
--------------------------------------------------------------------------------
/templates/cloudflare/public/_routes.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "include": ["/*"],
4 | "exclude": ["/favicon.ico", "/assets/*"]
5 | }
6 |
--------------------------------------------------------------------------------
/templates/cloudflare/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/cloudflare/public/favicon.ico
--------------------------------------------------------------------------------
/templates/cloudflare/public/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/cloudflare/public/logo-dark.png
--------------------------------------------------------------------------------
/templates/cloudflare/public/logo-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/cloudflare/public/logo-light.png
--------------------------------------------------------------------------------
/templates/cloudflare/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | export default {
4 | content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
5 | theme: {
6 | extend: {
7 | fontFamily: {
8 | sans: [
9 | "Inter",
10 | "ui-sans-serif",
11 | "system-ui",
12 | "sans-serif",
13 | "Apple Color Emoji",
14 | "Segoe UI Emoji",
15 | "Segoe UI Symbol",
16 | "Noto Color Emoji",
17 | ],
18 | },
19 | },
20 | },
21 | plugins: [],
22 | } satisfies Config;
23 |
--------------------------------------------------------------------------------
/templates/cloudflare/vite.config.ts:
--------------------------------------------------------------------------------
1 | import {
2 | vitePlugin as remix,
3 | cloudflareDevProxyVitePlugin as remixCloudflareDevProxy,
4 | } from "@remix-run/dev";
5 | import { defineConfig } from "vite";
6 | import tsconfigPaths from "vite-tsconfig-paths";
7 |
8 | declare module "@remix-run/cloudflare" {
9 | interface Future {
10 | v3_singleFetch: true;
11 | }
12 | }
13 |
14 | export default defineConfig({
15 | plugins: [
16 | remixCloudflareDevProxy(),
17 | remix({
18 | future: {
19 | v3_fetcherPersist: true,
20 | v3_relativeSplatPath: true,
21 | v3_throwAbortReason: true,
22 | v3_singleFetch: true,
23 | v3_lazyRouteDiscovery: true,
24 | },
25 | }),
26 | tsconfigPaths(),
27 | ],
28 | });
29 |
--------------------------------------------------------------------------------
/templates/express/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | .env
6 |
--------------------------------------------------------------------------------
/templates/express/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/express/app/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | html,
6 | body {
7 | @apply bg-white dark:bg-gray-950;
8 |
9 | @media (prefers-color-scheme: dark) {
10 | color-scheme: dark;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/express/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/templates/express/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/express/public/favicon.ico
--------------------------------------------------------------------------------
/templates/express/public/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/express/public/logo-dark.png
--------------------------------------------------------------------------------
/templates/express/public/logo-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/express/public/logo-light.png
--------------------------------------------------------------------------------
/templates/express/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | export default {
4 | content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
5 | theme: {
6 | extend: {
7 | fontFamily: {
8 | sans: [
9 | "Inter",
10 | "ui-sans-serif",
11 | "system-ui",
12 | "sans-serif",
13 | "Apple Color Emoji",
14 | "Segoe UI Emoji",
15 | "Segoe UI Symbol",
16 | "Noto Color Emoji",
17 | ],
18 | },
19 | },
20 | },
21 | plugins: [],
22 | } satisfies Config;
23 |
--------------------------------------------------------------------------------
/templates/express/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig } from "vite";
3 | import tsconfigPaths from "vite-tsconfig-paths";
4 |
5 | declare module "@remix-run/node" {
6 | interface Future {
7 | v3_singleFetch: true;
8 | }
9 | }
10 |
11 | export default defineConfig({
12 | plugins: [
13 | remix({
14 | future: {
15 | v3_fetcherPersist: true,
16 | v3_relativeSplatPath: true,
17 | v3_throwAbortReason: true,
18 | v3_singleFetch: true,
19 | v3_lazyRouteDiscovery: true,
20 | },
21 | }),
22 | tsconfigPaths(),
23 | ],
24 | });
25 |
--------------------------------------------------------------------------------
/templates/remix-javascript/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | .env
6 |
--------------------------------------------------------------------------------
/templates/remix-javascript/app/entry.client.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/remix-javascript/app/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | html,
6 | body {
7 | @apply bg-white dark:bg-gray-950;
8 |
9 | @media (prefers-color-scheme: dark) {
10 | color-scheme: dark;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/remix-javascript/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/templates/remix-javascript/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/remix-javascript/public/favicon.ico
--------------------------------------------------------------------------------
/templates/remix-javascript/public/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/remix-javascript/public/logo-dark.png
--------------------------------------------------------------------------------
/templates/remix-javascript/public/logo-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/remix-javascript/public/logo-light.png
--------------------------------------------------------------------------------
/templates/remix-javascript/tailwind.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
3 | theme: {
4 | extend: {
5 | fontFamily: {
6 | sans: [
7 | "Inter",
8 | "ui-sans-serif",
9 | "system-ui",
10 | "sans-serif",
11 | "Apple Color Emoji",
12 | "Segoe UI Emoji",
13 | "Segoe UI Symbol",
14 | "Noto Color Emoji",
15 | ],
16 | },
17 | },
18 | },
19 | plugins: [],
20 | };
21 |
--------------------------------------------------------------------------------
/templates/remix-javascript/vite.config.js:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig } from "vite";
3 |
4 | export default defineConfig({
5 | plugins: [
6 | remix({
7 | future: {
8 | v3_fetcherPersist: true,
9 | v3_relativeSplatPath: true,
10 | v3_throwAbortReason: true,
11 | v3_singleFetch: true,
12 | v3_lazyRouteDiscovery: true,
13 | },
14 | }),
15 | ],
16 | });
17 |
--------------------------------------------------------------------------------
/templates/remix-tutorial/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | .env
6 |
--------------------------------------------------------------------------------
/templates/remix-tutorial/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to Remix!
2 |
3 | - [Remix Docs](https://remix.run/docs)
4 |
5 | ## Development
6 |
7 | From your terminal:
8 |
9 | ```sh
10 | npm run dev
11 | ```
12 |
13 | This starts your app in development mode, rebuilding assets on file changes.
14 |
15 | ## Deployment
16 |
17 | First, build your app for production:
18 |
19 | ```sh
20 | npm run build
21 | ```
22 |
23 | Then run the app in production mode:
24 |
25 | ```sh
26 | npm start
27 | ```
28 |
29 | Now you'll need to pick a host to deploy it to.
30 |
31 | ### DIY
32 |
33 | If you're familiar with deploying node applications, the built-in Remix app server is production-ready.
34 |
35 | Make sure to deploy the output of `remix build`
36 |
37 | - `build/server`
38 | - `build/client`
39 |
--------------------------------------------------------------------------------
/templates/remix-tutorial/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/remix-tutorial/public/favicon.ico
--------------------------------------------------------------------------------
/templates/remix-tutorial/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig } from "vite";
3 | import tsconfigPaths from "vite-tsconfig-paths";
4 |
5 | export default defineConfig({
6 | plugins: [
7 | remix({
8 | ignoredRouteFiles: ["**/*.css"],
9 | }),
10 | tsconfigPaths(),
11 | ],
12 | });
13 |
--------------------------------------------------------------------------------
/templates/remix/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | .env
6 |
--------------------------------------------------------------------------------
/templates/remix/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/remix/app/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | html,
6 | body {
7 | @apply bg-white dark:bg-gray-950;
8 |
9 | @media (prefers-color-scheme: dark) {
10 | color-scheme: dark;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/remix/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/templates/remix/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/remix/public/favicon.ico
--------------------------------------------------------------------------------
/templates/remix/public/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/remix/public/logo-dark.png
--------------------------------------------------------------------------------
/templates/remix/public/logo-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/remix/public/logo-light.png
--------------------------------------------------------------------------------
/templates/remix/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | export default {
4 | content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
5 | theme: {
6 | extend: {
7 | fontFamily: {
8 | sans: [
9 | "Inter",
10 | "ui-sans-serif",
11 | "system-ui",
12 | "sans-serif",
13 | "Apple Color Emoji",
14 | "Segoe UI Emoji",
15 | "Segoe UI Symbol",
16 | "Noto Color Emoji",
17 | ],
18 | },
19 | },
20 | },
21 | plugins: [],
22 | } satisfies Config;
23 |
--------------------------------------------------------------------------------
/templates/remix/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig } from "vite";
3 | import tsconfigPaths from "vite-tsconfig-paths";
4 |
5 | declare module "@remix-run/node" {
6 | interface Future {
7 | v3_singleFetch: true;
8 | }
9 | }
10 |
11 | export default defineConfig({
12 | plugins: [
13 | remix({
14 | future: {
15 | v3_fetcherPersist: true,
16 | v3_relativeSplatPath: true,
17 | v3_throwAbortReason: true,
18 | v3_singleFetch: true,
19 | v3_lazyRouteDiscovery: true,
20 | },
21 | }),
22 | tsconfigPaths(),
23 | ],
24 | });
25 |
--------------------------------------------------------------------------------
/templates/spa/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | /.cache
4 | /build
5 | /public/build
6 | .env
7 |
--------------------------------------------------------------------------------
/templates/spa/app/entry.client.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * By default, Remix will handle hydrating your app on the client for you.
3 | * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
4 | * For more information, see https://remix.run/file-conventions/entry.client
5 | */
6 |
7 | import { RemixBrowser } from "@remix-run/react";
8 | import { startTransition, StrictMode } from "react";
9 | import { hydrateRoot } from "react-dom/client";
10 |
11 | startTransition(() => {
12 | hydrateRoot(
13 | document,
14 |
15 |
16 |
17 | );
18 | });
19 |
--------------------------------------------------------------------------------
/templates/spa/app/tailwind.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | html,
6 | body {
7 | @apply bg-white dark:bg-gray-950;
8 |
9 | @media (prefers-color-scheme: dark) {
10 | color-scheme: dark;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/templates/spa/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/templates/spa/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/spa/public/favicon.ico
--------------------------------------------------------------------------------
/templates/spa/public/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/spa/public/logo-dark.png
--------------------------------------------------------------------------------
/templates/spa/public/logo-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/remix-run/remix/2e74a9f4b9ced338100e3f6d18fe1d72f36418cd/templates/spa/public/logo-light.png
--------------------------------------------------------------------------------
/templates/spa/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | export default {
4 | content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"],
5 | theme: {
6 | extend: {
7 | fontFamily: {
8 | sans: [
9 | "Inter",
10 | "ui-sans-serif",
11 | "system-ui",
12 | "sans-serif",
13 | "Apple Color Emoji",
14 | "Segoe UI Emoji",
15 | "Segoe UI Symbol",
16 | "Noto Color Emoji",
17 | ],
18 | },
19 | },
20 | },
21 | plugins: [],
22 | } satisfies Config;
23 |
--------------------------------------------------------------------------------
/templates/spa/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["env.d.ts", "**/*.ts", "**/*.tsx"],
3 | "compilerOptions": {
4 | "lib": ["DOM", "DOM.Iterable", "ES2022"],
5 | "types": ["@remix-run/node", "vite/client"],
6 | "isolatedModules": true,
7 | "esModuleInterop": true,
8 | "jsx": "react-jsx",
9 | "module": "ESNext",
10 | "moduleResolution": "Bundler",
11 | "resolveJsonModule": true,
12 | "target": "ES2022",
13 | "strict": true,
14 | "allowJs": true,
15 | "skipLibCheck": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "~/*": ["./app/*"]
20 | },
21 |
22 | // Remix takes care of building everything in `remix build`.
23 | "noEmit": true
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/templates/spa/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { vitePlugin as remix } from "@remix-run/dev";
2 | import { defineConfig } from "vite";
3 | import tsconfigPaths from "vite-tsconfig-paths";
4 |
5 | declare module "@remix-run/node" {
6 | interface Future {
7 | v3_singleFetch: true;
8 | }
9 | }
10 |
11 | export default defineConfig({
12 | plugins: [
13 | remix({
14 | ssr: false,
15 | future: {
16 | v3_fetcherPersist: true,
17 | v3_relativeSplatPath: true,
18 | v3_throwAbortReason: true,
19 | v3_singleFetch: true,
20 | v3_lazyRouteDiscovery: true,
21 | },
22 | }),
23 | tsconfigPaths(),
24 | ],
25 | });
26 |
--------------------------------------------------------------------------------