ProTemplates

Ledgerly, Pro

A revenue app for a subscription business on Stripe, for Next.js. Install it into a new project, then rewrite its sample API to read your own data.

Ledgerly is a whole app made of Dashboardblocks blocks: Overview, Subscriptions, Customers with a page for each customer, an Inbox, and Settings for the profile, workspace, members, billing, single sign-on and the audit log. Every page reads and writes through one sample API, so the app works as soon as it's installed. Open the preview to try it first.

Install

Ledgerly comes with All-Access and installs with the shadcn CLI.

  1. Make a Next.js project with shadcn set up, at shadcn create (opens in a new tab) or with the CLI:

    npx shadcn@latest init --template next
  2. Add the @dashboardblocks-pro registry and your token, as Installation shows.

  3. Install Ledgerly:

    npx shadcn@latest add @dashboardblocks-pro/ledgerly-next --overwrite
  4. Run npm run dev and open /overview.

With --overwrite, the CLI replaces any file you have that Ledgerly also ships, such as shadcn components and blocks you've changed and a proxy.ts, so commit first and check the diff. Without it, the CLI asks about each of those files, and skips them all when it can't ask. Your root layout, home page and theme stay as they are, and Ledgerly takes your shadcn style, component library and icon set.

What it adds

PathWhat's there
app/(ledgerly)/The routes. Each one loads its page's data from the sample API and passes it to the page.
components/ledgerly/pages/A component per page. They take data and callbacks as props and know nothing about Next.js.
lib/ledgerly/api/The sample API: async functions in index.ts, their types in types.ts and the sample data in data/.
components/ledgerly/next/The layout, the session and the Server Actions every page shares.
components/ledgerly/routes.tsThe list of pages that the sidebar, breadcrumbs and ⌘K search read.
components/ledgerly/The parts every page shares: the app shell, the logo, the link adapter, and the connection and plan notices.
lib/ledgerly/Helpers the pages share: the CSV download and the row a subscription table reads.
proxy.tsRuns Ledgerly's proxy on its pages.

In a project with a src/ folder, they go in src/. The blocks Ledgerly uses install next to your other blocks in components/dashboardblocks/.

Use your own data

Pages never load data themselves. Each route file calls functions from lib/ledgerly/api, and each change goes through a Server Action that calls one too. To show your own data, rewrite the bodies of those functions and keep their types. The pages, routes and actions stay as they are.

  1. Start with the page you need first. Its route file in app/(ledgerly)/ names the functions it calls, such as getOverview for Overview.
  2. Rewrite each function to query your database or Stripe's API, and return the type types.ts gives it. A write returns a result the page shows, such as a refusal with its reason, so keep returning one.
  3. Once nothing in index.ts reads data/ any more, delete data/.

Every function takes the session first. Every write, and every read that only some roles may make, checks the member's role in one table, permissions in index.ts. Keep that check, or move it to where your app checks access.

Add your auth

components/ledgerly/next/session.ts gives every page the signed-in member, { memberId }. For now it signs in the same sample member every time. Change getSession and isSignedOut to read your auth library's session.

The /sign-in and /sign-out routes in proxy.ts stand in for your auth library's own. Once you add yours, take them out of its matcher and out of components/ledgerly/next/proxy.ts, and point the sign-in and sign-out links in components/ledgerly/next/next-shell.tsx at your library's pages.

If you had a proxy.ts before, put yours back and call ledgerlyProxy(request) from components/ledgerly/next/proxy.ts for the paths in the matcher of the one Ledgerly installed.

On this page