arandu-io/arandu
The project skeleton aru new clones — a running application from the first commit.
About the skeleton
Note: this is what a new project starts from. The framework it runs on is
arandu-io/framework.
You do not clone it by hand:
aru new my-app
cd my-app && aru dev
That gives you a Go framework for web applications, services and APIs, built
around development speed, a single compiled binary instead of a JavaScript
bundle, and authorization the compiler charges for: a repository call with no
Grant does not compile.
What it delivers
- A conventional tree —
app/Http/Controllers,app/Models,
app/Policies, app/Repositories, app/Services, app/Jobs,
app/Events, app/Listeners, app/Mail, bootstrap/, config/,
database/, resources/views/, routes/, storage/, public/ — so
nothing about where a file lives has to be learned.
- A mandatory
app/Policies/— elsewhere a policy directory is a habit an
aru doctor fails a repository whose entity has no
policy, and the policy denies by default with no allow-all branch.
- A binary, not a toolchain — it runs with
git clone && aru dev. No
node_modules, no package.json, no JavaScript lockfile, and no Node
installed: the view compiler and every script are embedded in the binary.
bootstrap/app.go— the one place the application is wired.aru
The example resource
A fresh project carries one small, complete resource, notes, so the first
thing you read is a whole module that works rather than an empty directory. It
was written by aru make:module note --fields "title:string!,body:text,pinned:bool" --tenant,
aru make:factory Note and aru make:seeder Note, and then opened by hand
where the generator stops: an author column, the policy rules, and the author
set from the signed-in subject. It is the reference for the shape of every
module you add:
NoteControllerreads who is asking withctx.User()behind
middleware.RequireAuth, binds the form with ctx.Bind and returns every
error to the router, which answers validation with the form, a missing row
with 404 and a refusal with 403;
NoteServicevalidates, asksNotePolicyfor aGrant, and reads and writes
models.Notes(db) with FindOrFail, SimplePaginate and Save;
NotePolicylets anybody signed in to the tenant read and write notes, and
tests/Feature/Notes_test.goproves the whole path in a browser, including a
aru migrate creates the table and aru db:seed writes six notes in
development, by two accounts nobody can sign in as. To use it in a browser,
publish the sign-in screens with go run github.com/arandu-io/ui@latest auth,
make your own account with
aru db:seed UserSeeder -e [email protected] -p , sign in, and
open /notes: the seeded notes are there to read, and refused to change,
because you did not write them.
Removing it
There is no command for it. Delete these files:
.agents/skills/notes/SKILL.md
app/Http/Controllers/NoteController.go
app/Http/Requests/NoteRequest.go
app/Models/Note.go
app/Models/NoteQuery.go (generated; aru model:build also removes it once Note.go is gone)
app/Policies/NotePolicy.go
app/Services/NoteService.go
database/factories/NoteFactory.go
database/migrations/2026_10_01_000001_create_notes_table.go
database/seeders/NoteSeeder.go
resources/views/notes/ (the directory, four views)
resources/views/partials/notes_table.kyse.go
storage/framework/views/notes/ (the directory, compiled output)
storage/framework/views/partials/notes_table.go (compiled output)
tests/Feature/Notes_test.go
tests/Unit/Note_test.go
and these lines, each marked with a comment naming this section:
routes/web.go Note *controllers.NoteController
routes/web.go r.Group("", middleware.RequireAuth(d.Sessions)).Resource("notes", d.Note)
bootstrap/app.go Note: controllers.NewNoteController(services.NewNoteService(db)),
bootstrap/app.go _ ".../storage/framework/views/partials" (once no other partial is left)
database/seeders/seeders.go NoteSeeder{},
database/seeders/DatabaseSeeder.go return NoteSeeder{}.Run(ctx, d) (becomes: return nil)
tests/Feature/TenantScope_test.go "notes": "...",
A database that already ran the migration keeps the table: in development run
aru migrate:fresh after deleting the files; anywhere else add a migration
that drops notes. Then aru view:build, go test ./... and aru doctor.
aru doctor checks this tree against the architecture rules — from a
repository missing its policy to a tenant read off the request instead of the
Grant — and CI runs it on every push, without --strict: an error fails the
build, a warning stays the to-do it is, and a new project is never red for code
the generator wrote.
6,973 lines of production code and 9,593 of test, across 49 test files, the example resource included — small on purpose: it is what a project starts from, not what it grows into.
The rest of Arandu
aru is the command line that clones and drives this skeleton;
arandu-io/framework is what it
runs on; hesape is the component collection the framework is built from;
examples is a complete application, read-worthy end to end, built the same
way aru new starts one.
Learning Arandu
The API reference is generated from the doc comments and lives on pkg.go.dev. Every exported symbol carries one, and that is deliberate: it is the documentation that cannot drift from the code, because it sits in the same file.
The CLI documents itself. aru help lists every command, and each one explains
what it writes and what to do with it. aru doctor explains what it found and
what breaks, not which rule was violated.
The guide is published at arandu.io/docs, and the site is itself an Arandu application. Where the guide and a doc comment disagree, the doc comment sits next to the code and is the one to trust.
Contributing
See CONTRIBUTING.md. Before opening a pull request, the three
commands under "Before you open a pull request" have to pass — CI runs them, and
then the binary, aru doctor, the image and govulncheck on top.
Security Vulnerabilities
Please review our security policy on how to report a vulnerability. Never open a public issue for one.
License
Open-sourced software licensed under the MIT license.