init
This commit is contained in:
7
.env
Normal file
7
.env
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Environment variables declared in this file are automatically made available to Prisma.
|
||||||
|
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
|
||||||
|
|
||||||
|
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB (Preview).
|
||||||
|
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
||||||
|
|
||||||
|
DATABASE_URL="postgresql://admin:password@localhost:32760/app"
|
||||||
3
.eslintrc
Normal file
3
.eslintrc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"extends": ["@remix-run/eslint-config", "@remix-run/eslint-config/node"]
|
||||||
|
}
|
||||||
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
node_modules
|
||||||
|
|
||||||
|
/.cache
|
||||||
|
/build
|
||||||
|
/public/build
|
||||||
|
*.env.*
|
||||||
|
!*.env
|
||||||
2
Procfile
Normal file
2
Procfile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
web: npm run start
|
||||||
|
release: npx prisma migrate deploy
|
||||||
15
README.md
Normal file
15
README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[](https://heroku.com/deploy?template=https://github.com/TerribleDev/remix-heroku)
|
||||||
|
|
||||||
|
# Remix stack for heroku
|
||||||
|
|
||||||
|
This is a very simple remix stack built for heroku. This includes:
|
||||||
|
|
||||||
|
* dotenv to load environment variables
|
||||||
|
* Postgres Sql for a datastore
|
||||||
|
* Prism ORM for database queries
|
||||||
|
|
||||||
|
## Developing
|
||||||
|
|
||||||
|
You can use `docker-compose up -d` to boot postgres locally, and the connection strings you need are in `.env`.
|
||||||
|
|
||||||
|
You should make an `.env.development` file to store all your local environment settings to keep out of git
|
||||||
28
app.json
Normal file
28
app.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "Remix on heroku",
|
||||||
|
"description": "A sample app showing remix on heroku with postgres",
|
||||||
|
"keywords": [
|
||||||
|
"react",
|
||||||
|
"remix",
|
||||||
|
"postgres"
|
||||||
|
|
||||||
|
],
|
||||||
|
"website": "https://github.com/TerribleDev/remix-heroku",
|
||||||
|
"repository": "https://github.com/TerribleDev/remix-heroku.git",
|
||||||
|
"success_url": "/",
|
||||||
|
"scripts": {},
|
||||||
|
"formation": {
|
||||||
|
"web": {
|
||||||
|
"quantity": 1,
|
||||||
|
"size": "hobby"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"addons": [
|
||||||
|
"heroku-postgresql"
|
||||||
|
],
|
||||||
|
"buildpacks": [
|
||||||
|
{
|
||||||
|
"url": "heroku/nodejs"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
4
app/entry.client.tsx
Normal file
4
app/entry.client.tsx
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { RemixBrowser } from "@remix-run/react";
|
||||||
|
import { hydrate } from "react-dom";
|
||||||
|
|
||||||
|
hydrate(<RemixBrowser />, document);
|
||||||
22
app/entry.server.tsx
Normal file
22
app/entry.server.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import 'dotenv/config'
|
||||||
|
import type { EntryContext } from "@remix-run/node";
|
||||||
|
import { RemixServer } from "@remix-run/react";
|
||||||
|
import { renderToString } from "react-dom/server";
|
||||||
|
|
||||||
|
export default function handleRequest(
|
||||||
|
request: Request,
|
||||||
|
responseStatusCode: number,
|
||||||
|
responseHeaders: Headers,
|
||||||
|
remixContext: EntryContext
|
||||||
|
) {
|
||||||
|
let markup = renderToString(
|
||||||
|
<RemixServer context={remixContext} url={request.url} />
|
||||||
|
);
|
||||||
|
|
||||||
|
responseHeaders.set("Content-Type", "text/html");
|
||||||
|
|
||||||
|
return new Response("<!DOCTYPE html>" + markup, {
|
||||||
|
status: responseStatusCode,
|
||||||
|
headers: responseHeaders,
|
||||||
|
});
|
||||||
|
}
|
||||||
32
app/root.tsx
Normal file
32
app/root.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import type { MetaFunction } from "@remix-run/node";
|
||||||
|
import {
|
||||||
|
Links,
|
||||||
|
LiveReload,
|
||||||
|
Meta,
|
||||||
|
Outlet,
|
||||||
|
Scripts,
|
||||||
|
ScrollRestoration,
|
||||||
|
} from "@remix-run/react";
|
||||||
|
|
||||||
|
export const meta: MetaFunction = () => ({
|
||||||
|
charset: "utf-8",
|
||||||
|
title: "New Remix App",
|
||||||
|
viewport: "width=device-width,initial-scale=1",
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<Meta />
|
||||||
|
<Links />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Outlet />
|
||||||
|
<ScrollRestoration />
|
||||||
|
<Scripts />
|
||||||
|
<LiveReload />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
app/routes/index.tsx
Normal file
30
app/routes/index.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
import type { LoaderFunction } from "@remix-run/node";
|
||||||
|
import { json } from "@remix-run/node";
|
||||||
|
import { useLoaderData } from "@remix-run/react";
|
||||||
|
import type { Note } from "@prisma/client";
|
||||||
|
|
||||||
|
import { db } from "~/utils/db.server";
|
||||||
|
|
||||||
|
type LoaderData = { notes: Array<Note> };
|
||||||
|
|
||||||
|
export const loader: LoaderFunction = async () => {
|
||||||
|
const data: LoaderData = {
|
||||||
|
notes: await db.note.findMany(),
|
||||||
|
};
|
||||||
|
return json(data);
|
||||||
|
};
|
||||||
|
export default function Index() {
|
||||||
|
const data = useLoaderData<LoaderData>();
|
||||||
|
return (
|
||||||
|
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
|
||||||
|
<h1>Welcome to Remix Heroku</h1>
|
||||||
|
<p> Notes: </p>
|
||||||
|
<ul>
|
||||||
|
{data.notes.map(({ id, name }) => ( <li key={name}>id: {id} name: {name}</li>))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
21
app/utils/db.server.ts
Normal file
21
app/utils/db.server.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
|
||||||
|
let db: PrismaClient;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var __db: PrismaClient | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is needed because in development we don't want to restart
|
||||||
|
// the server with every change, but we want to make sure we don't
|
||||||
|
// create a new connection to the DB with every change either.
|
||||||
|
if (process.env.NODE_ENV === "production") {
|
||||||
|
db = new PrismaClient();
|
||||||
|
} else {
|
||||||
|
if (!global.__db) {
|
||||||
|
global.__db = new PrismaClient();
|
||||||
|
}
|
||||||
|
db = global.__db;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { db };
|
||||||
11
docker-compose.yml
Normal file
11
docker-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- '32760:5432'
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: 'password'
|
||||||
|
POSTGRES_USER: 'admin'
|
||||||
16946
package-lock.json
generated
Normal file
16946
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
37
package.json
Normal file
37
package.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"name": "remix-template-remix",
|
||||||
|
"private": true,
|
||||||
|
"description": "",
|
||||||
|
"license": "",
|
||||||
|
"sideEffects": false,
|
||||||
|
"scripts": {
|
||||||
|
"build": "remix build",
|
||||||
|
"dev": "remix dev",
|
||||||
|
"start": "remix-serve build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@prisma/client": "^3.12.0",
|
||||||
|
"@remix-run/node": "^1.3.4",
|
||||||
|
"@remix-run/react": "^1.3.4",
|
||||||
|
"@remix-run/serve": "^1.3.4",
|
||||||
|
"dotenv": "^16.0.0",
|
||||||
|
"prisma": "^3.12.0",
|
||||||
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@remix-run/dev": "^1.3.4",
|
||||||
|
"@remix-run/eslint-config": "^1.3.4",
|
||||||
|
"@types/react": "^17.0.24",
|
||||||
|
"@types/react-dom": "^17.0.9",
|
||||||
|
"esbuild-register": "^3.3.2",
|
||||||
|
"eslint": "^8.11.0",
|
||||||
|
"typescript": "^4.5.5"
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"seed": "node --require esbuild-register prisma/seed.ts"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
prisma/migrations/20220407132919_init/migration.sql
Normal file
7
prisma/migrations/20220407132919_init/migration.sql
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Note" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"name" TEXT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Note_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Please do not edit this file manually
|
||||||
|
# It should be added in your version-control system (i.e. Git)
|
||||||
|
provider = "postgresql"
|
||||||
17
prisma/schema.prisma
Normal file
17
prisma/schema.prisma
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// This is your Prisma schema file,
|
||||||
|
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
model Note {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
name String
|
||||||
|
}
|
||||||
8
prisma/seed.ts
Normal file
8
prisma/seed.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
const db = new PrismaClient();
|
||||||
|
|
||||||
|
async function seed() {
|
||||||
|
return db.note.create({ data: { name: "Note from the databae" }});
|
||||||
|
}
|
||||||
|
|
||||||
|
seed();
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
10
remix.config.js
Normal file
10
remix.config.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* @type {import('@remix-run/dev').AppConfig}
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
ignoredRouteFiles: [".*"],
|
||||||
|
// appDirectory: "app",
|
||||||
|
// assetsBuildDirectory: "public/build",
|
||||||
|
// serverBuildPath: "build/index.js",
|
||||||
|
// publicPath: "/build/",
|
||||||
|
};
|
||||||
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ES2019"],
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"target": "ES2019",
|
||||||
|
"strict": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["./app/*"]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Remix takes care of building everything in `remix build`.
|
||||||
|
"noEmit": true
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user