32
loading...
This website collects cookies to deliver better user experience
yarn create redwood-app stepzen-redwood-posts
cd stepzen-redwood-posts
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
binaryTargets = "native"
}
model Post {
id Int @id @default(autoincrement())
title String
body String
createdAt DateTime @default(now())
}
railway login
🚝 Logging in... No dice? Try railway login --browserless
🚄 Logging in...
🎉 Logged in as Anthony Campolo ([email protected])
railway init
✔ Create new Project
✔ Enter project name: stepzen-redwood-posts
✔ Environment: production
🎉 Created project stepzen-redwood-posts
railway add
✔ Plugin: postgresql
🎉 Created plugin postgresql
.env
file with your DATABASE_URL.echo DATABASE_URL=`railway variables get DATABASE_URL` > .env
yarn rw prisma migrate dev
generates the folders and files necessary to create a new migration. We will name our migration posts-table
.yarn rw prisma migrate dev --name posts-table
yarn rw g scaffold post
http://localhost:8910/posts
to create a couple blog posts.yarn rw dev
yarn rw setup deploy netlify
netlify.toml
file:[build]
command = "yarn rw deploy netlify"
publish = "web/dist"
functions = "api/dist/functions"
[dev]
framework = "redwoodjs"
targetPort = 8910
port = 8888
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
build
command is yarn rw deploy netlify
publish
directory for your assets is web/dist
functions
will be in api/dist/functions
git init
git add .
git commit -m "posts"
git remote add origin https://github.com/ajcwebdev/stepzen-redwood-posts.git
git push -u origin main
DATABASE_URL
environment variable and add ?connection_limit=1
to the end or your database will spontaneously burst into flames.https://stepzen-redwood-posts.netlify.app/.netlify/functions/graphql
.query getPosts {
posts {
id
title
body
createdAt
}
}
yarn create redwood-app stepzen-redwood-users
cd stepzen-redwood-users
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
binaryTargets = "native"
}
model User {
id Int @id @default(autoincrement())
name String
}
railway init
✔ Create new Project
✔ Enter project name: stepzen-redwood-users
✔ Environment: production
🎉 Created project stepzen-redwood-users
railway add
✔ Plugin: postgresql
🎉 Created plugin postgresql
.env
file with your DATABASE_URL.echo DATABASE_URL=`railway variables get DATABASE_URL` > .env
yarn rw prisma migrate dev
generates the folders and files necessary to create a new migration. We will name our migration users-table
.yarn rw prisma migrate dev --name users-table
yarn rw g scaffold user
http://localhost:8910/users
to create a couple users.yarn rw dev
yarn rw setup deploy netlify
git init
git add .
git commit -m "users"
git remote add origin https://github.com/ajcwebdev/stepzen-redwood-users.git
git push -u origin main
DATABASE_URL
environment variable and add ?connection_limit=1
to the end or your database will spontaneously burst into flames.https://stepzen-redwood-posts.netlify.app/.netlify/functions/graphql
.query getUsers {
users {
id
name
}
}
@graphql
directive.mkdir stepzen-redwood-mesh
cd stepzen-redwood-mesh
index.graphql
file.touch index.graphql
schema
@sdl(
files: [
"schema/posts.graphql"
"schema/users.graphql"
]
) {
query: Query
}
schema
directory will contain files for each GraphQL API.mkdir schema
posts.graphql
file for your Post
type.touch schema/posts.graphql
type Post {
id: Int!
title: String!
body: String!
createdAt: DateTime!
}
type Query {
posts: [Post!]!
@graphql(
endpoint:"https://stepzen-redwood-posts.netlify.app/.netlify/functions/graphql"
)
}
users.graphql
file for your User
type.touch schema/users.graphql
type User {
id: Int!
name: String!
}
type Query {
users: [User!]!
@graphql(
endpoint:"https://stepzen-redwood-users.netlify.app/.netlify/functions/graphql"
)
}
stepzen start
api/stepzen-redwood-mesh
.query MySuperAwesomeQueryThatWontFail {
users {
name
id
}
posts {
title
id
createdAt
body
}
}
yarn create redwood-app stepzen-metawood
cd stepzen-metawood
api/src
directory contains all the other backend code for a Redwood app and includes four directories:functions
graphql
lib
services
functions
directory contains a graphql.js
file auto-generated by Redwood that is required to use the GraphQL API. Since we will not use the Prisma client or a database that Redwood comes preconfigured for, we can replace the default template with the following code.// api/src/functions/graphql.js
import {
createGraphQLHandler,
makeMergedSchema,
makeServices,
} from '@redwoodjs/api'
import schemas from 'src/graphql/**/*.{js,ts}'
import services from 'src/services/**/*.{js,ts}'
export const handler = createGraphQLHandler({
schema: makeMergedSchema({
schemas,
services: makeServices({ services }),
}),
})
graphql
directory contains posts.sdl.js
with your GraphQL schema written in the Schema Definition Language. This will ensure that our Redwood API will have a schema
that matches our schema
in posts.graphql
.touch api/src/graphql/posts.sdl.js
Post
type, and each Post
has an id
, title
, body
, and createdAt
date just like our StepZen schema. The posts
query returns an array of Post
objects.// api/src/graphql/posts.sdl.js
export const schema = gql`
type Post {
id: ID
title: String
body: String
createdAt: String
}
type Query {
posts: [Post]
}
`
users.sdl.js
file so our Redwood API will have a schema
that matches our schema
in users.graphql
.touch api/src/graphql/users.sdl.js
User
type, and each User
has an id
and name
just like our StepZen schema. The users
query returns an array of User
objects.// api/src/graphql/users.sdl.js
export const schema = gql`
type User {
id: ID
name: String
}
type Query {
users: [User]
}
`
web
side includes Apollo Client by default, its api
side does not include any built in mechanism for making HTTP requests.graphql-request
to connect to services such as Contentful, AppSync, Hasura, and FaunaDB. First, we need to install graphql-request
as a dependency on the api
side.yarn workspace api add graphql-request
db.js
to client.js
mv api/src/lib/db.js api/src/lib/client.js
// api/src/lib/client.js
import { GraphQLClient } from 'graphql-request'
export const request = async (query = {}) => {
const endpoint = process.env.API_ENDPOINT
const graphQLClient = new GraphQLClient(endpoint, {
headers: {
authorization: 'apikey ' + process.env.API_KEY
},
})
try {
return await graphQLClient.request(query)
} catch (err) {
console.log(err)
return err
}
}
graphql-request
to connect to StepZen and query the API along with our StepZen API key in the header for authorization.endpoint
is set to the url generated when we deployed our API with stepzen start
.authorization
includes your StepZen API key appended to apikey
. You can get your API key on your my account page..env
file that will contain our StepZen API key and endpoint URL.API_ENDPOINT=<YOUR_API_ENDPOINT>
API_KEY=<YOUR_API_KEY>
services
directory we will create a posts
directory with a posts.js
service and a users
directory with a users.js
service. These files will send GraphQL queries to our StepZen API.mkdir api/src/services/posts api/src/services/users
touch api/src/services/posts/posts.js api/src/services/users/users.js
// api/src/services/posts/posts.js
import { request } from 'src/lib/client'
import { gql } from 'graphql-request'
export const posts = async () => {
const GET_POSTS_QUERY = gql`
query getPosts {
posts {
id
title
body
createdAt
}
}
`
const data = await request(GET_POSTS_QUERY)
return data['posts']
}
GET_POSTS_QUERY
is sent with the GraphQLClient
imported from src/lib/client
. The query is asking for the list of posts
and their id
, title
, body
, and createdAt
date.// api/src/services/users/users.js
import { request } from 'src/lib/client'
import { gql } from 'graphql-request'
export const users = async () => {
const GET_USERS_QUERY = gql`
query getUsers {
users {
id
name
}
}
`
const data = await request(GET_USERS_QUERY)
return data['users']
}
GET_USERS_QUERY
is sent with the GraphQLClient
imported from src/lib/client
. The query is asking for the list of users
and their id
and name
.api
side can be accessed through a GraphiQL explorer running on localhost:8911/graphql
.web
side contains a PostsCell
for fetching posts
, a UsersCell
for fetching users
, and a HomePage
for rendering the cell.PostsCell
.yarn rw g cell posts
getPosts
returns the id
, title
, body
, and createdAt
date of each post
. This will send the query to our api
side, which in turn sends a query to our StepZen API which in turn sends a query to our stepzen-redwood-posts
API. Once the results are returned, they will be output on the page. Redwood automatically adds basic handling for the Loading
, Empty
and Failure
states.// web/src/components/PostsCell/PostsCell.js
export const QUERY = gql`
query getPosts {
posts {
id
title
body
createdAt
}
}
`
export const Loading = () => <div>Almost there...</div>
export const Empty = () => <div>WE NEED POSTS</div>
export const Failure = ({ error }) => <div>{error.message}</div>
export const Success = ({ posts }) => {
return (
<ul>
{posts.map(post => (
<li>{post.title}</li>
))}
</ul>
)
}
UsersCell
.yarn rw g cell users
getUsers
returns the id
and name
of each user
. This will send the query to our api
side, which in turn sends a query to our StepZen API which in turn sends a query to our stepzen-redwood-users
API.// web/src/components/UsersCell/UsersCell.js
export const QUERY = gql`
query getUsers {
users {
id
name
}
}
`
export const Loading = () => <div>Almost there...</div>
export const Empty = () => <div>WE NEED USERS</div>
export const Failure = ({ error }) => <div>{error.message}</div>
export const Success = ({ users }) => {
return (
<ul>
{users.map(user => (
<li>{user.name}</li>
))}
</ul>
)
}
yarn rw g page home /
PostsCell
and UsersCell
to display the information fetched by the respective cell's queries.// web/src/pages/HomePage/HomePage.js
import PostsCell from 'src/components/PostsCell'
import UsersCell from 'src/components/UsersCell'
const HomePage = () => {
return (
<>
<h1>StepZen+Metawood</h1>
<h2>Posts</h2>
<PostsCell />
<h2>Users</h2>
<UsersCell />
</>
)
}
export default HomePage