Skip to content

Pylon’s New Pages Router – Full-Stack Support Coming! Feedback Wanted! #69

@schettn

Description

@schettn

🚀 Pylon’s New Pages Router – Full-Stack Support Coming! Feedback Wanted! 🚀

I’m working on full-stack support for Pylon with a React Pages Router, similar to Next.js, bringing SSR & Hydration! 🎉

🔹 What’s New?

Nested Pages with Layouts
Efficient SSR with Partial Data Fetching
Automatic Hydration with GQTY’s useQuery
PostCSS Support (e.g., TailwindCSS)
Full-Stack Development (frontend + backend, but keeping them separate)


📂 Project Structure

With the new Pages Router, your Pylon app structure looks like this:

pages/                # Frontend pages (outside src!)
 ├── page.tsx        # Root page ("/")
 ├── layout.tsx      # Root layout
 ├── [slug]/         # Dynamic route (e.g., "/blog/:slug")
 │   ├── page.tsx    # Page for dynamic route
 │   ├── layout.tsx  # Layout for this route
src/                  # Backend logic (GraphQL API)
 ├── index.ts        # Pylon backend logic

🛠️ Backend – src/index.ts (GraphQL API)

Pylon remains GraphQL-first – your backend logic lives in src/index.ts as usual.

import {app, usePages, PylonConfig} from '@getcronit/pylon'

export const graphql = {
  Query: {
    hello: () => {
      return 'Hello, world!'
    },
    post: (slug: string) => {
      return {title: `Post: ${slug}`, content: 'This is a blog post.'}
    }
  }
}

export const config: PylonConfig = {
  plugins: [usePages()] // Enables the Pages Router
}

export default app

📄 Frontend – Pages Structure

1️⃣ Pages (pages/page.tsx)

Pages receive a data prop (from GQTY’s useQuery) and params from the URL.

import {PageProps} from '@getcronit/pylon'

const Page: React.FC<PageProps> = ({data}) => {
  return (
    <>
      <title>{data.hello}</title>
      <h1>{data.hello}</h1>
    </>
  )
}

export default Page

2️⃣ Layouts (pages/layout.tsx)

Layouts wrap child pages and persist across navigation.

import {LayoutProps} from '@getcronit/pylon'

const Layout: React.FC<LayoutProps> = ({children}) => {
  return (
    <div>
      <header>My App</header>
      <main>{children}</main>
    </div>
  )
}

export default Layout

3️⃣ Dynamic Routes (pages/[slug]/page.tsx)

The params object is used to pass dynamic values (e.g., /blog/my-post).

import {PageProps} from '@getcronit/pylon'

const Page: React.FC<PageProps> = ({data, params}) => {
  return (
    <>
      <title>{data.post({slug: params.slug}).title}</title>
      <h1>{data.post({slug: params.slug}).title}</h1>
      <p>{data.post({slug: params.slug}).content}</p>
    </>
  )
}

export default Page

4️⃣ Nested Layouts (pages/[slug]/layout.tsx)

Each route can have its own layout.

import {LayoutProps} from '@getcronit/pylon'

const BlogLayout: React.FC<LayoutProps> = ({children}) => {
  return (
    <div>
      <aside>Blog Sidebar</aside>
      <section>{children}</section>
    </div>
  )
}

export default BlogLayout

How Data Fetching Works

🔹 During SSR, Pylon only fetches the fields used in the page.
🔹 This data is cached and sent to the client for hydration.
🔹 When new fields are accessed on the client, they are refetched dynamically.

This keeps API requests efficient and minimal while making development seamless!


🔥 Why This Matters

Unlike traditional full-stack frameworks, Pylon keeps GraphQL API and UI separate:

  • GraphQL API remains clean and usable by other clients.
  • Pages Router integrates seamlessly but does not mix backend logic inside components.

💡 I Need Your Feedback!

This feature is under development, and I’d love your input:

  • Does this pages structure make sense?
  • Would you use this for full-stack development?
  • Any features or improvements you’d like to see?

Let me know what you think! 🚀

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions